<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>文档</title>
  <link href="./css/semantic/semantic.min.css" rel="stylesheet">
  <link href="./css/oscTree.css" rel="stylesheet">
  <link href="./css/markdown.css" rel="stylesheet">
  <link href="./css/index.css" rel="stylesheet">
</head>
<body>
  <div class="ui container">
    <div id="project-title">
      <div class="title-wrap">
        <div class="left">
          <i class="icon eye"></i>
          文档预览:
          <span id="preview-title"></span>
        </div>
        <div class="right">
          Export by Gitee
        </div>
      </div>
    </div>

    <div class="ui container" id="wiki-preview-container">
      <div id="wiki-preview">
        <div class="ui segment">
          <div class="ui grid page">
            <div class="three wide column doc-list">
              <div class="title">
                <a id="ex-all">
                  收缩全部章节
                </a>
              </div>
              <div class="ztree" id="tree"></div>
            </div>
            <div class="thirteen wide column doc-content">
              <div id="page-detail">
                <div class="title">
                </div>
                <div class="content markdown-body">
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      </div>
  </div>
</body>
</html>
<script src="./js/jquery.min.js"></script>
<script src="./js/ztree.all.js"></script>
<script src="./js/jquery.ztree.exhide.min.js"></script>
<script>
  var zTreeObj;var expandStatus=true;$(document).ready(function(){var setting={view:{showLine:true,showIcon:true},callback:{onClick:function(e,treeId,treeNode){if(treeNode!==null&&!treeNode.isParent&&typeof(treeNode.children)==="undefined"){var sort_id=treeNode.sort_id;var content=json_data.content;for(var c in content){if(c==sort_id){$("#page-detail .title").html(treeNode.name);$("#page-detail .content").html(content[c]);return false}}}else{zTreeObj.expandNode(treeNode)}}},data:{simpleData:{enable:true}}};zTreeObj=$.fn.zTree.init($("#tree"),setting,json_data.title);var first_content=json_data.title[0];$("#page-detail .title").html(first_content.name);$("#page-detail .content").html(json_data.content[first_content.sort_id]);$("#preview-title").html(json_data.preview_title);$("#ex-all").on("click",function(e){zTreeObj.expandAll(!expandStatus);expandStatus=!expandStatus;if(expandStatus){$(this).text("收缩全部章节")}else{$(this).text("展开全部章节")}})});
</script><script>var json_data = {"preview_title":"1. 架构师教程","title":[{"id":"8676f23","pId":"c21f20d","name":"01 springboot","parent":"八、框架","sort_id":1164285,"order":-1,"isParent":true,"extname":null,"open":false},{"id":"d1f6d69","pId":"83ae707","name":"01 redis","parent":"四、数据库","sort_id":987070,"order":-1,"isParent":true,"extname":null,"open":false},{"id":"1.2.3.1 集群搭建","pId":"c07e325","name":"1.2.3.1 集群搭建","parent":"四、数据库/01 redis/1.2 redis 高级/1.2.3 集群","order":-1,"sort_id":1027404,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/feiyun126/p/7248989.html\"\u003Eredis4集群\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-下载redis-401并解压\" class=\"anchor\" href=\"#2-%E4%B8%8B%E8%BD%BDredis-401%E5%B9%B6%E8%A7%A3%E5%8E%8B\"\u003E\u003C/a\u003E2. 下载redis-4.0.1并解压\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E解压目录：/usr/local/redis-4.0.1\n建立软连接：ln -s redis-4.0.1 redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-编译安装\" class=\"anchor\" href=\"#3-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E3. 编译安装\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E指定安装目录到:/usr/local/redis\n\nmake \u0026amp;\u0026amp; make install PREFIX=/usr/local/redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-节点准备\" class=\"anchor\" href=\"#4-%E8%8A%82%E7%82%B9%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E4. 节点准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E节点分配信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E主机\u003C/th\u003E\n\u003Cth\u003E端口\u003C/th\u003E\n\u003Cth\u003E主从\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Enode1_192.168.222.132\u003C/td\u003E\n\u003Ctd\u003E7001\u003C/td\u003E\n\u003Ctd\u003E主\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Enode1_192.168.222.132\u003C/td\u003E\n\u003Ctd\u003E7002\u003C/td\u003E\n\u003Ctd\u003E从\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Enode2_192.168.222.133\u003C/td\u003E\n\u003Ctd\u003E7003\u003C/td\u003E\n\u003Ctd\u003E主\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Enode2_192.168.222.133\u003C/td\u003E\n\u003Ctd\u003E7004\u003C/td\u003E\n\u003Ctd\u003E从\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Enode3_192.168.222.134\u003C/td\u003E\n\u003Ctd\u003E7005\u003C/td\u003E\n\u003Ctd\u003E主\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Enode3_192.168.222.135\u003C/td\u003E\n\u003Ctd\u003E7006\u003C/td\u003E\n\u003Ctd\u003E从\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置节点信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# node1服务器:\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7001\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7002\n\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7001\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7002\n\n# node2服务器:\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7003\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7004\n\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7003\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7004\n\n# node3服务器:\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7005\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7006\n\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7005\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7006\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-修改redisconfig\" class=\"anchor\" href=\"#5-%E4%BF%AE%E6%94%B9redisconfig\"\u003E\u003C/a\u003E5. 修改redis.config\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E值\u003C/th\u003E\n\u003Cth\u003E说明\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Eport\u003C/td\u003E\n\u003Ctd\u003E7000\u003C/td\u003E\n\u003Ctd\u003E端口号\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ebind\u003C/td\u003E\n\u003Ctd\u003E本机ip\u003C/td\u003E\n\u003Ctd\u003E根据本机所在的IP或hostname去配制 node1 node2 node3\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Edaemonize\u003C/td\u003E\n\u003Ctd\u003Eyes\u003C/td\u003E\n\u003Ctd\u003Eredis后台运行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Edir\u003C/td\u003E\n\u003Ctd\u003E/usr/local/deve/soft/redis-cluster/700*/\u003C/td\u003E\n\u003Ctd\u003E指定数据文件存放目录\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Epidfile\u003C/td\u003E\n\u003Ctd\u003E/var/run/redis_7000.pid\u003C/td\u003E\n\u003Ctd\u003Epidfile文件对应7000,7001,7002,7003,7004,7005\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ecluster-enabled\u003C/td\u003E\n\u003Ctd\u003Eyes\u003C/td\u003E\n\u003Ctd\u003E开启集群  把注释#去掉\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Ecluster-config-file\u003C/td\u003E\n\u003Ctd\u003Enodes_7000.conf\u003C/td\u003E\n\u003Ctd\u003E集群的配置  配置文件首次启动自动生成 7000,7001,7002,7003,7004,7005\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ecluster-node-timeout\u003C/td\u003E\n\u003Ctd\u003E15000\u003C/td\u003E\n\u003Ctd\u003E请求超时  默认15秒，可自行设置\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Eappendonly\u003C/td\u003E\n\u003Ctd\u003Eyes\u003C/td\u003E\n\u003Ctd\u003Eaof日志开启  有需要就开启，它会每次写操作都记录一条日志\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Elogfile\u003C/td\u003E\n\u003Ctd\u003E/usr/local/deve/soft/redis-cluster//7001.log\u003C/td\u003E\n\u003Ctd\u003E日志目录\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-安装ruby环境\" class=\"anchor\" href=\"#6-%E5%AE%89%E8%A3%85ruby%E7%8E%AF%E5%A2%83\"\u003E\u003C/a\u003E6. 安装ruby环境\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install -y ruby\nyum install -y rubygems\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"7-安装ruby的包\" class=\"anchor\" href=\"#7-%E5%AE%89%E8%A3%85ruby%E7%9A%84%E5%8C%85\"\u003E\u003C/a\u003E7. 安装ruby的包\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Egem install redis\n\n如果不成功需要去下载后安装\n下载地址\nhttps://rubygems.org/gems/redis/versions/4.0.0.rc1\nhttps://rubygems.org/downloads/redis-4.0.0.rc1.gem\n\n安装命令：gem install -l ./redis-4.0.0.rc1.gem\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"8-启动各个节点\" class=\"anchor\" href=\"#8-%E5%90%AF%E5%8A%A8%E5%90%84%E4%B8%AA%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E8. 启动各个节点\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# node1服务器:\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7001/redis.conf\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7002/redis.conf\n\n# node2服务器:\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7003/redis.conf\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7004/redis.conf\n\n# node3服务器:\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7005/redis.conf\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7006/redis.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"9-检查各节点是否启动\" class=\"anchor\" href=\"#9-%E6%A3%80%E6%9F%A5%E5%90%84%E8%8A%82%E7%82%B9%E6%98%AF%E5%90%A6%E5%90%AF%E5%8A%A8\"\u003E\u003C/a\u003E9. 检查各节点是否启动\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E查看进程\nps -ef | grep redis\n\n查看端口\nnetstat -tnlp | grep redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"10-创建集群\" class=\"anchor\" href=\"#10-%E5%88%9B%E5%BB%BA%E9%9B%86%E7%BE%A4\"\u003E\u003C/a\u003E10. 创建集群\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 进入node1的bin目录下,执行以下脚本\n./redis-trib.rb  create  --replicas  1  node1:7001 node1:7002  node2:7003  node2:7004  node3:7005  node3:7006\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E--replicas  1 : 主/从=1\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# ./redis-trib.rb  create  --replicas  1  127.0.0.1:7001 127.0.0.1:7002  127.0.0.1:7003  127.0.0.1:7004  127.0.0.1:7005  127.0.0.1:7006\n\n./redis-trib.rb  create  --replicas  1  127.0.0.1:7001 127.0.0.1:7002  127.0.0.1:7003  127.0.0.1:7004  127.0.0.1:7005  127.0.0.1:7006\n\n./redis-trib.rb  create  --replicas  1  192.168.222.129:7001 192.168.222.129:7002  192.168.222.129:7003  192.168.222.129:7004  192.168.222.129:7005  192.168.222.129:7006\n\n\n\u0026gt;\u0026gt;\u0026gt; Creating cluster\n\u0026gt;\u0026gt;\u0026gt; Performing hash slots allocation on 6 nodes...\nUsing 3 masters:\n127.0.0.1:7001\n127.0.0.1:7002\n127.0.0.1:7003\nAdding replica 127.0.0.1:7005 to 127.0.0.1:7001\nAdding replica 127.0.0.1:7006 to 127.0.0.1:7002\nAdding replica 127.0.0.1:7004 to 127.0.0.1:7003\n\u0026gt;\u0026gt;\u0026gt; Trying to optimize slaves allocation for anti-affinity\n[WARNING] Some slaves are in the same host as their master\nM: e0be2ed1522678a87ac7c7d717404a41cff8c324 127.0.0.1:7001\n   slots:0-5460 (5461 slots) master\nM: 12a9e2e40beb5fa2799715fa35b8d770dd4a4669 127.0.0.1:7002\n   slots:5461-10922 (5462 slots) master\nM: 7415681580ed3f02f98abd36816f45d38d462198 127.0.0.1:7003\n   slots:10923-16383 (5461 slots) master\nS: af1103565bbeae4147e931bad6699df121040cae 127.0.0.1:7004\n   replicates 7415681580ed3f02f98abd36816f45d38d462198\nS: 3bea7a226f979b2741e2d4eea6934d9342cababd 127.0.0.1:7005\n   replicates e0be2ed1522678a87ac7c7d717404a41cff8c324\nS: c1051cc7b154a5a536bce536865a06d67a618218 127.0.0.1:7006\n   replicates 12a9e2e40beb5fa2799715fa35b8d770dd4a4669\nCan I set the above configuration? (type 'yes' to accept): yes\n\u0026gt;\u0026gt;\u0026gt; Nodes configuration updated\n\u0026gt;\u0026gt;\u0026gt; Assign a different config epoch to each node\n\u0026gt;\u0026gt;\u0026gt; Sending CLUSTER MEET messages to join the cluster\nWaiting for the cluster to join...\n\u0026gt;\u0026gt;\u0026gt; Performing Cluster Check (using node 127.0.0.1:7001)\nM: e0be2ed1522678a87ac7c7d717404a41cff8c324 127.0.0.1:7001\n   slots:0-5460 (5461 slots) master\n   1 additional replica(s)\nS: af1103565bbeae4147e931bad6699df121040cae 127.0.0.1:7004\n   slots: (0 slots) slave\n   replicates 7415681580ed3f02f98abd36816f45d38d462198\nS: c1051cc7b154a5a536bce536865a06d67a618218 127.0.0.1:7006\n   slots: (0 slots) slave\n   replicates 12a9e2e40beb5fa2799715fa35b8d770dd4a4669\nS: 3bea7a226f979b2741e2d4eea6934d9342cababd 127.0.0.1:7005\n   slots: (0 slots) slave\n   replicates e0be2ed1522678a87ac7c7d717404a41cff8c324\nM: 7415681580ed3f02f98abd36816f45d38d462198 127.0.0.1:7003\n   slots:10923-16383 (5461 slots) master\n   1 additional replica(s)\nM: 12a9e2e40beb5fa2799715fa35b8d770dd4a4669 127.0.0.1:7002\n   slots:5461-10922 (5462 slots) master\n   1 additional replica(s)\n[OK] All nodes agree about slots configuration.\n\u0026gt;\u0026gt;\u0026gt; Check for open slots...\n\u0026gt;\u0026gt;\u0026gt; Check slots coverage...\n[OK] All 16384 slots covered.\n[root@localhost src]# \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"11-验证集群\" class=\"anchor\" href=\"#11-%E9%AA%8C%E8%AF%81%E9%9B%86%E7%BE%A4\"\u003E\u003C/a\u003E11. 验证集群\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E进入每台服务器的redis/src目录,记住参数  -c不可以少\n\nredis-cli -h node1 -p 7001 -c\n\nredis-cli -h node2 -p 7003 -c\n\nredis-cli -h node3 -p 7005 -c\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"f417e8e","pId":0,"name":"一、并发编程","parent":"","sort_id":672490,"order":0,"isParent":true,"extname":null,"open":false},{"id":"2fc41b2","pId":"f417e8e","name":"01  线程基础","parent":"一、并发编程","sort_id":672496,"order":0,"isParent":true,"extname":null,"open":false},{"id":"1.1 线程安全","pId":"2fc41b2","name":"1.1 线程安全","parent":"一、并发编程/01  线程基础","order":0,"sort_id":672495,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-什么叫线程安全\" class=\"anchor\" href=\"#1-%E4%BB%80%E4%B9%88%E5%8F%AB%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8\"\u003E\u003C/a\u003E1. 什么叫线程安全：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E如果你的代码所在的进程中有多个线程在同时运行，而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的，而且其他的变量的值也和预期的是一样的，\n就是线程安全的。\u003C/li\u003E\n\u003Cli\u003E或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。\n线程安全问题都是由全局变量及静态变量引起的。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-测试demo\" class=\"anchor\" href=\"#2-%E6%B5%8B%E8%AF%95demo\"\u003E\u003C/a\u003E2. 测试demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.thread;\n\n\n/**\n * \u0026lt;p\u0026gt;\n *  类描述 :  synchronized：可以在任意对象及方法上加锁，而加锁的这段代码称为\"互斥区\"或\"临界区\"\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/21\n */\npublic class MyThread extends Thread {\n\n    private int count = 5;\n\n    //synchronized加锁\n    @Override\n    public synchronized void run() {\n        count--;\n        String name = MyThread.currentThread().getName();\n        System.out.println(\"name :\" + name + \" =========  count: \" + count);\n    }\n\n    public static void  main(String[] args) {\n        MyThread myThread = new MyThread() ;\n        Thread t1 = new Thread(myThread , \"t1\") ;\n        Thread t2 = new Thread(myThread , \"t2\") ;\n        Thread t3 = new Thread(myThread , \"t3\") ;\n        Thread t4 = new Thread(myThread , \"t4\") ;\n        Thread t5 = new Thread(myThread , \"t5\") ;\n\n        t1.start();\n        t2.start();\n        t3.start();\n        t4.start();\n        t5.start();\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当run方法不进行synchronized加锁时，输出结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0821/145305_fa3d3b06_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当run方法进行synchronized加锁时，输出结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0821/145329_e1c99369_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例说明\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E3. 示例说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E当多个线程访问MyThread的run方法时，以排队的方式进行处理（这里排队是按照CPU分配的先后顺序而定）\u003C/li\u003E\n\u003Cli\u003E一个线程想要执行synchronized修饰的方法时，首先要获得锁，只有获得锁才能执行synchronized代码体内容，这个线程会一直尝试，直到获得锁为止\u003C/li\u003E\n\u003Cli\u003E多个线程竞争一把锁，会导致锁竞争\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.1 多线程通信","pId":"77fbb9c","name":"2.1 多线程通信","parent":"一、并发编程/02 多线程通信","order":0,"sort_id":685536,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1demo1\" class=\"anchor\" href=\"#1demo1\"\u003E\u003C/a\u003E（1）demo1\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ListAdd1 {\n\n    private volatile static List list = new ArrayList();\n\n    public void add() {\n        list.add(\"bjsxt\");\n    }\n\n    public int size() {\n        return list.size();\n    }\n\n    public static void main(String[] args) {\n\n        final ListAdd1 list1 = new ListAdd1();\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    for (int i = 0; i \u0026lt; 10; i++) {\n                        list1.add();\n                        System.out.println(\"当前线程：\"\n                                + Thread.currentThread().getName() + \"添加了一个元素..\");\n                        Thread.sleep(500);\n                    }\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }\n        }, \"t1\");\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                while (true) {\n                    if (list1.size() == 5) {\n                        System.out.println(\"当前线程收到通知：\"\n                                + Thread.currentThread().getName() + \" list size = 5 线程停止..\");\n                        throw new RuntimeException();\n                    }\n                }\n            }\n        }, \"t2\");\n\n        t1.start();\n        t2.start();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E线程t2需要一直循环等待，造成浪费\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2demo2\" class=\"anchor\" href=\"#2demo2\"\u003E\u003C/a\u003E（2）demo2\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ListAdd3 {\n\n    private volatile static List list = new ArrayList();\n\n    public void add() {\n        list.add(\"bjsxt\");\n    }\n\n    public int size() {\n        return list.size();\n    }\n\n    public static void main(String[] args) {\n\n        final ListAdd3 listAdd3 = new ListAdd3();\n\n        final Object lock = new Object();\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                synchronized (lock){\n                    for (int i = 0 ; i \u0026lt; 10 ; i++) {\n                        listAdd3.add();\n                        System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"添加了一个元素..\");\n                        try {\n                            Thread.sleep(500);\n                            if (listAdd3.size() == 5) {\n                                System.out.println(\"已经发出通知..\");\n                                lock.notify();  // notify 不释放锁\n                            }\n                        } catch (InterruptedException e) {\n                            e.printStackTrace();\n                        }\n\n                    }\n                }\n            }\n        });\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                synchronized (lock){\n                    if (listAdd3.size() != 5) {\n                        try {\n                            System.out.println(\"t2进入...\");\n                            lock.wait();\n                        } catch (InterruptedException e) {\n                            e.printStackTrace();\n                        }\n                    }\n                    System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"收到通知线程停止..\");\n                    throw new RuntimeException();\n                }\n            }\n        });\n\n        t2.start();\n        t1.start();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E注意：t2一定要先执行\u003C/li\u003E\n\u003Cli\u003Ewait()、notify()必须结合synchronized一起使用\u003C/li\u003E\n\u003Cli\u003Elock.wait() 会释放锁，让t1获取锁\u003C/li\u003E\n\u003Cli\u003Elock.notify() 不释放锁，虽然在通知了，但是线程t2还是无法及时获得锁对象，需等t1执行结束后才获得\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3demo3\" class=\"anchor\" href=\"#3demo3\"\u003E\u003C/a\u003E（3）demo3\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ListAdd4 {\n\n    private volatile static List list = new ArrayList();\n\n    public void add() {\n        list.add(\"bjsxt\");\n    }\n\n    public int size() {\n        return list.size();\n    }\n\n    public static void  main(String[] args) {\n\n        final ListAdd4 listAdd4 = new ListAdd4();\n\n        final CountDownLatch countDownLatch = new CountDownLatch(1);\n\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                for (int i = 0 ; i \u0026lt; 10 ; i++){\n                    listAdd4.add();\n                    System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"添加了一个元素..\");\n                    if (listAdd4.size() == 5) {\n                        System.out.println(\"已经发出通知..\");\n                        countDownLatch.countDown();\n                    }\n                    try {\n                        Thread.sleep(500);\n                    } catch (InterruptedException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        }, \"t1\");\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                if (listAdd4.size() != 5) {\n                    try {\n                        countDownLatch.await();\n                    } catch (InterruptedException e) {\n                        e.printStackTrace();\n                    }\n                }\n\n                System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"收到通知线程停止..\");\n                throw new RuntimeException();\n            }\n        } , \"t2\");\n\n        t2.start();\n        t1.start();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用CountDownLatch，可以解决demo2中问题，t1一发出通知，t2即可执行\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.4.1 高并发容器","pId":"75d372a","name":"2.4.1 高并发容器","parent":"一、并发编程/02 多线程通信/2.4 高并发容器","order":0,"sort_id":697207,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1concurrent\" class=\"anchor\" href=\"#1concurrent\"\u003E\u003C/a\u003E1、Concurrent\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class UseConcurrentMap {\n\n\tpublic static void main(String[] args) {\n\t\tConcurrentHashMap\u0026lt;String, Object\u0026gt; chm = new ConcurrentHashMap\u0026lt;String, Object\u0026gt;();\n\t\tchm.put(\"k1\", \"v1\");\n\t\tchm.put(\"k2\", \"v2\");\n\t\tchm.put(\"k3\", \"v3\");\n\t\tchm.putIfAbsent(\"k4\", \"vvvv\");\n\t\t//System.out.println(chm.get(\"k2\"));\n\t\t//System.out.println(chm.size());\n\t\t\n\t\tfor(Map.Entry\u0026lt;String, Object\u0026gt; me : chm.entrySet()){\n\t\t\tSystem.out.println(\"key:\" + me.getKey() + \",value:\" + me.getValue());\n\t\t}\n\t\t\n\t\t\n\t\t\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E将容器分段（最高16段），处理高并发写的\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2copyonwritecow\" class=\"anchor\" href=\"#2copyonwritecow\"\u003E\u003C/a\u003E2.CopyOnWrite（cow）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class UseCopyOnWrite {\n\n\tpublic static void main(String[] args) {\n\t\t\n\t\tCopyOnWriteArrayList\u0026lt;String\u0026gt; cwal = new CopyOnWriteArrayList\u0026lt;String\u0026gt;();\n\t\tCopyOnWriteArraySet\u0026lt;String\u0026gt; cwas = new CopyOnWriteArraySet\u0026lt;String\u0026gt;();\n\t\t\n\t\t\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E处理高并发读，读不加锁\u003C/li\u003E\n\u003Cli\u003E每次写都需要加锁，复制原先的记录，然后进行修改，修改结束后把指针指向新的空间，旧空间释放（垃圾回收）\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.5.1 生产者与消费者","pId":"b6b90b0","name":"2.5.1 生产者与消费者","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":0,"sort_id":729009,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-创建消息类\" class=\"anchor\" href=\"#1-%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%E7%B1%BB\"\u003E\u003C/a\u003E1. 创建消息类\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 : 消息对象\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class Msg {\n\n    private int id;\n\n    private String name;\n\n    public Msg(int id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    @Override\n    public String toString() {\n        return \"Msg{\" +\n                \"id=\" + id +\n                \", name='\" + name + '\\'' +\n                '}';\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-创建消息生产者\" class=\"anchor\" href=\"#2-%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E8%80%85\"\u003E\u003C/a\u003E2. 创建消息生产者\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class MsgProvider implements Runnable {\n\n    /**\n     * 消息队列\n     */\n    private BlockingQueue\u0026lt;Msg\u0026gt; queue;\n\n    /**\n     * 是否执行\n     */\n    private boolean isRunning = true;\n\n    /**\n     * 用于生成id\n     */\n    private static AtomicInteger ids = new AtomicInteger(0);\n\n    /**\n     * 用于生成随机数\n     */\n    private Random random = new Random();\n\n\n    @Override\n    public void run() {\n        while (isRunning) {\n            try {\n                // 模拟生产数据浪费时间\n                Thread.sleep(random.nextInt(1000));\n\n                int id = ids.incrementAndGet() ;\n                Msg msg = new Msg(id , \"数据_\" + id) ;\n\n                String threadName = Thread.currentThread().getName() ;\n                if (!queue.offer(msg , 2 , TimeUnit.SECONDS)){\n                    System.out.println(threadName+ \"数据生成识别\");\n                }else {\n                    System.out.println(threadName+ \"数据生成\" + msg);\n                }\n\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n\n    /**\n     * 构造方法，传入消息队列\n     *\n     * @param queue\n     */\n    public MsgProvider(BlockingQueue\u0026lt;Msg\u0026gt; queue) {\n        this.queue = queue;\n    }\n\n\n    /**\n     * 停止执行\n     */\n    public void stop() {\n        this.isRunning = false;\n    }\n\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E注意：ids 必须声明成static才能保证多线程的原子性\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-消息消费者\" class=\"anchor\" href=\"#3-%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85\"\u003E\u003C/a\u003E3. 消息消费者\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 : 消息消费者\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class MsgConsumer implements Runnable {\n\n    /**\n     * 消息队列\n     */\n    private BlockingQueue\u0026lt;Msg\u0026gt; queue ;\n\n    /**\n     * 是否执行\n     */\n    private boolean isRunning = true ;\n\n    /**\n     * 用于生成随机数\n     */\n    private Random random = new Random();\n\n\n    @Override\n    public void run() {\n        while (isRunning){\n            try {\n                Msg msg = queue.take() ;\n                //进行数据处理。休眠0 - 1000毫秒模拟耗时\n                Thread.sleep(random.nextInt(1000));\n                System.out.println(\"当前消费线程：\" + Thread.currentThread().getName() + \"， 消费成功，消费数据为id: \" + msg);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n        }\n    }\n\n\n    /**\n     * 构造方法，传入消息队列\n     *\n     * @param queue\n     */\n    public MsgConsumer(BlockingQueue\u0026lt;Msg\u0026gt; queue){\n        this.queue = queue ;\n    }\n\n\n    /**\n     * 停止执行\n     */\n    public void stop(){\n        this.isRunning = false ;\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-测试\" class=\"anchor\" href=\"#4-%E6%B5%8B%E8%AF%95\"\u003E\u003C/a\u003E4. 测试\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class MsgMain {\n\n    public static void  main(String[] args) throws Exception {\n\n        // 消息队列\n        BlockingQueue\u0026lt;Msg\u0026gt; queue = new LinkedBlockingDeque\u0026lt;Msg\u0026gt;();\n\n        // 创建消息生产者\n        MsgProvider p1 = new MsgProvider(queue);\n        MsgProvider p2 = new MsgProvider(queue);\n        MsgProvider p3 = new MsgProvider(queue);\n\n\n        // 创建消息消费者\n        MsgConsumer c1 = new MsgConsumer(queue);\n        MsgConsumer c2 = new MsgConsumer(queue);\n        MsgConsumer c3 = new MsgConsumer(queue);\n\n        // 创建线程池，执行线程\n        ExecutorService executorService = Executors.newCachedThreadPool();\n        executorService.execute(p1);\n        executorService.execute(p2);\n        executorService.execute(p3);\n\n        executorService.execute(c1);\n        executorService.execute(c2);\n        executorService.execute(c3);\n\n        // 休眠3s后停止生产\n        Thread.sleep(3000);\n        p1.stop();\n        p2.stop();\n        p3.stop();\n\n        // 休眠3s后停止消费\n        Thread.sleep(3000);\n        c1.stop();\n        c2.stop();\n        c3.stop();\n\n        executorService.shutdown();\n\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.6.1 CountDownLatch","pId":"3b56f09","name":"2.6.1 CountDownLatch","parent":"一、并发编程/02 多线程通信/2.6 concurrent工具类","order":0,"sort_id":736283,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.util.Random;\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 : 测试CountDownLatch\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/10\n */\npublic class TestCountDownLatch {\n\n\n    public static void main(String[] args) {\n\n        final CountDownLatch countDownLatch = new CountDownLatch(2);\n\n        /**\n         * 主线程\n         */\n        new Thread(() -\u0026gt; {\n            try {\n                // 进入等待\n                countDownLatch.await();\n                System.out.println(\"所有线程都执行完毕....\");\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n        }).start();\n\n\n        for (int i = 0; i \u0026lt; 2; i++) {\n            final int t = i;\n            new Thread(() -\u0026gt; {\n                try {\n                    System.out.println(\"线程\" + t + \"开始....\");\n                    Thread.sleep(new Random().nextInt(2000));\n                    // 进行计数\n                    countDownLatch.countDown();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }).start();\n        }\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0910/103119_6066e67e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ECountDownLatch是在java1.5被引入的，它存在于java.util.concurrent包下。\u003C/li\u003E\n\u003Cli\u003ECountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行\u003C/li\u003E\n\u003Cli\u003ECountDownLatch是通过一个计数器来实现的，计数器的初始值为线程的数量。每当一个线程完成了自己的任务后，计数器的值就会减1。当计数器值到达0时，它表示所有的线程已经完成了任务，然后在闭锁上等待的线程就可以恢复执行任务\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0910/100926_10734d14_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-使用场景\" class=\"anchor\" href=\"#3-%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF\"\u003E\u003C/a\u003E3. 使用场景\u003C/h3\u003E\n\u003Cp\u003E（1）实现最大的并行性：有时我们想同时启动多个线程，实现最大程度的并行性。例如，我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch，并让所有线程都在这个锁上等待，那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。\u003C/p\u003E\n\u003Cp\u003E（2）开始执行前等待n个线程完成各自任务：例如应用程序启动类要确保在处理用户请求前，所有N个外部系统已经启动和运行了。\u003C/p\u003E\n\u003Cp\u003E（3）死锁检测：一个非常方便的使用场景是，你可以使用n个线程访问共享资源，在每次测试阶段的线程数目是不同的，并尝试产生死锁。\u003C/p\u003E"},{"id":"2.7.1 基础用法","pId":"5fc2e0f","name":"2.7.1 基础用法","parent":"一、并发编程/02 多线程通信/2.7 Lock 锁","order":0,"sort_id":798468,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/25\n */\npublic class TestReentranLock {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n\n    /**\n     * 定义锁\n     */\n    private Lock lock = new ReentrantLock();\n\n\n    /**\n     * 执行方法\n     */\n    public void m1() {\n        try {\n            lock.lock();\n            System.out.println(FORMAT.format(new Date()) + Thread.currentThread().getName() + \"--\u0026gt; m1 开始\");\n            Thread.sleep(1000);\n            System.out.println(FORMAT.format(new Date()) + Thread.currentThread().getName() + \"--\u0026gt; m1 结束\");\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n    public static void main(String[] args) {\n        final TestReentranLock test = new TestReentranLock();\n        /**\n         * 多线程执行，需要等上一线程执行完成，下一个线程才能开始\n         */\n        for (int i = 0; i \u0026lt; 3; i++) {\n            new Thread(() -\u0026gt; {\n                test.m1();\n            }, \"线程 t\" + i).start();\n        }\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0925/175700_9b2465da_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E多线程执行，需要等上一线程执行完成，下一个线程才能开始\u003C/li\u003E\n\u003Cli\u003E结合try...catch...finally 使用\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"7a86ec7","pId":"2116d9f","name":"01 软件安装","parent":"三、linux ","sort_id":987021,"order":0,"isParent":true,"extname":null,"open":false},{"id":"1.1 安装JDK ","pId":"7a86ec7","name":"1.1 安装JDK ","parent":"三、linux /01 软件安装","order":0,"sort_id":987022,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-安装准备\" class=\"anchor\" href=\"#1-%E5%AE%89%E8%A3%85%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E1. 安装准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E首先从官网上下载\u003Ca href=\"https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html\"\u003EJdk 8下载\u003C/a\u003E\n\u003C/li\u003E\n\u003Cli\u003E检查系统自带JDK\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Erpm -qa | grep java\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E卸载系统自带open jdk\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Erpm -e –-nodeps XXXX_openjdk_XXX \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E以上两步可以和在一起操作\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Erpm -e --nodeps `rpm -qa | grep java`\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-jdk的安装\" class=\"anchor\" href=\"#2-jdk%E7%9A%84%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. Jdk的安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压jdk压缩包\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar –xzvf jdk-8u45-linux-x64.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压后的jdk的文件夹名字为jdk1.8.0_45,我们把它改为jdk1.8\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Emv jdk1.8.0_45/ jdk1.8/\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-jdk的配置\" class=\"anchor\" href=\"#3-jdk%E7%9A%84%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3. jdk的配置\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用vim命令打开系统的环境变量配置文件：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evi /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在profile文件最后加入：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E## JAVA\n\nexport JAVA_HOME=/usr/local/deve/soft/jdk1.8\n\nexport PATH=$PATH:$JAVA_HOME/bin\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置文件立即生效\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esource /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-配置验证\" class=\"anchor\" href=\"#4-%E9%85%8D%E7%BD%AE%E9%AA%8C%E8%AF%81\"\u003E\u003C/a\u003E4. 配置验证\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E输入java –version，会得到：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003Ejava version \"1.8.0_45\"\u003C/p\u003E\n\u003Cp\u003EJava(TM) SE Runtime Environment (build 1.8.0_45-b14)\u003C/p\u003E\n\u003Cp\u003EJava HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)\u003C/p\u003E"},{"id":"2.1 CentOS7修改时区","pId":"6275c3c","name":"2.1 CentOS7修改时区","parent":"三、linux /02 系统操作","order":0,"sort_id":987032,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"centos7修改时区的正确姿势\" class=\"anchor\" href=\"#centos7%E4%BF%AE%E6%94%B9%E6%97%B6%E5%8C%BA%E7%9A%84%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF\"\u003E\u003C/a\u003ECentOS7修改时区的正确姿势\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"检查\" class=\"anchor\" href=\"#%E6%A3%80%E6%9F%A5\"\u003E\u003C/a\u003E检查\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Edate\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1a342f6","pId":"8b32ab8","name":"3.1 vi 命令","parent":"三、linux /03 常用命令","sort_id":987037,"order":0,"isParent":true,"extname":null,"open":false},{"id":"3.1.1 vi 介绍与配置","pId":"1a342f6","name":"3.1.1 vi 介绍与配置","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987038,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-vi的基本概念\" class=\"anchor\" href=\"#1-vi%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5\"\u003E\u003C/a\u003E1. vi的基本概念\u003C/h3\u003E\n\u003Cp\u003E　　基本上vi可以分为三种状态，分别是命令模式（command mode）、插入模式（Insert mode）和底行模式（last line mode），各模式的功能区分如下：\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E1) 命令行模式command mode）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E　　控制屏幕光标的移动，字符、字或行的删除，移动复制某区段及进入Insert mode下，或者到 last line mode。\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E2) 插入模式（Insert mode）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E　　只有在Insert mode下，才可以做文字输入，按「ESC」键可回到命令行模式。\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E3) 底行模式（last line mode）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E　　将文件保存或退出vi，也可以设置编辑环境，如寻找字符串、列出行号……等。\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E不过一般我们在使用时把vi简化成两个模式，就是将底行模式（last line mode）也算入命令行模式command mode）。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-修改vim配置信息\" class=\"anchor\" href=\"#2-%E4%BF%AE%E6%94%B9vim%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E2. 修改vim配置信息\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改用户配置信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim ~/.vimrc  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改全局配置信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/vimrc\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-可配置信息\" class=\"anchor\" href=\"#3-%E5%8F%AF%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E3. 可配置信息\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eall：列出所有选项设置情况 \nterm：设置终端类型 \nignorance：在搜索中忽略大小写 \nlist：显示制表位(Ctrl+I)和行尾标志（$) \nnumber：显示行号 \nreport：显示由面向行的命令修改过的数目 \nterse：显示简短的警告信息 \nwarn：在转到别的文件时若没保存当前文件则显示NO write信息 \nnomagic：允许在搜索模式中，使用前面不带“\\”的特殊字符 \nnowrapscan：禁止vi在搜索到达文件两端时，又从另一端开始 \nmesg：允许vi显示其他用户用write写到自己终端上的信息\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"3.1.2 进入vi 命令","pId":"1a342f6","name":"3.1.2 进入vi 命令","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987039,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-进入vi的命令\" class=\"anchor\" href=\"#1-%E8%BF%9B%E5%85%A5vi%E7%9A%84%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 进入vi的命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi filename\u003C/td\u003E\n\u003Ctd\u003E打开或新建文件，并将光标置于第一行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi +n filename\u003C/td\u003E\n\u003Ctd\u003E打开文件，并将光标置于第n行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi + filename\u003C/td\u003E\n\u003Ctd\u003E打开文件，并将光标置于最后一行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi +/pattern filename\u003C/td\u003E\n\u003Ctd\u003E打开文件，并将光标置于第一个与pattern匹配的串处\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi -r filename\u003C/td\u003E\n\u003Ctd\u003E在上次正用vi编辑时发生系统崩溃，恢复filename\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi filename....filename\u003C/td\u003E\n\u003Ctd\u003E打开多个文件，依次进行编辑\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"3.1.3 移动光标命令","pId":"1a342f6","name":"3.1.3 移动光标命令","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987040,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-移动光标类命令\" class=\"anchor\" href=\"#1-%E7%A7%BB%E5%8A%A8%E5%85%89%E6%A0%87%E7%B1%BB%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 移动光标类命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eh\u003C/td\u003E\n\u003Ctd\u003E光标左移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003El\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Espace\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EBackspace\u003C/td\u003E\n\u003Ctd\u003E光标左移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ek或Ctrl+p\u003C/td\u003E\n\u003Ctd\u003E光标上移一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ej或Ctrl+n\u003C/td\u003E\n\u003Ctd\u003E光标下移一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EEnter\u003C/td\u003E\n\u003Ctd\u003E光标下移一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ew或W\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字至字首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eb或B\u003C/td\u003E\n\u003Ctd\u003E光标左移一个字至字首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ee或E\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字至字尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E)\u003C/td\u003E\n\u003Ctd\u003E光标移至句尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E(\u003C/td\u003E\n\u003Ctd\u003E光标移至句首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E}\u003C/td\u003E\n\u003Ctd\u003E光标移至段落开头\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E{\u003C/td\u003E\n\u003Ctd\u003E光标移至段落结尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EnG\u003C/td\u003E\n\u003Ctd\u003E光标移至第n行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En+\u003C/td\u003E\n\u003Ctd\u003E光标下移n行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En-\u003C/td\u003E\n\u003Ctd\u003E光标上移n行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En$\u003C/td\u003E\n\u003Ctd\u003E光标移至第n行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EH\u003C/td\u003E\n\u003Ctd\u003E光标移至屏幕顶行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EM\u003C/td\u003E\n\u003Ctd\u003E光标移至屏幕中间行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EL\u003C/td\u003E\n\u003Ctd\u003E光标移至屏幕最后行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E0\u003C/td\u003E\n\u003Ctd\u003E（注意是数字零）光标移至当前行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E$\u003C/td\u003E\n\u003Ctd\u003E光标移至当前行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"3.1.4 屏幕翻滚类命令","pId":"1a342f6","name":"3.1.4 屏幕翻滚类命令","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987041,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-屏幕翻滚类命令\" class=\"anchor\" href=\"#1-%E5%B1%8F%E5%B9%95%E7%BF%BB%E6%BB%9A%E7%B1%BB%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 屏幕翻滚类命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+u\u003C/td\u003E\n\u003Ctd\u003E向文件首翻半屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+d\u003C/td\u003E\n\u003Ctd\u003E向文件尾翻半屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+f\u003C/td\u003E\n\u003Ctd\u003E向文件尾翻一屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl＋b\u003C/td\u003E\n\u003Ctd\u003E向文件首翻一屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Enz\u003C/td\u003E\n\u003Ctd\u003E将第n行滚至屏幕顶部，不指定n时将当前行滚至屏幕顶部。\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"3.1.5 插入命令","pId":"1a342f6","name":"3.1.5 插入命令","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987042,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-插入文本类命令\" class=\"anchor\" href=\"#1-%E6%8F%92%E5%85%A5%E6%96%87%E6%9C%AC%E7%B1%BB%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 插入文本类命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ei\u003C/td\u003E\n\u003Ctd\u003E在光标前\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EI\u003C/td\u003E\n\u003Ctd\u003E在当前行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ea\u003C/td\u003E\n\u003Ctd\u003E光标后\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EA\u003C/td\u003E\n\u003Ctd\u003E在当前行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eo\u003C/td\u003E\n\u003Ctd\u003E在当前行之下新开一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EO\u003C/td\u003E\n\u003Ctd\u003E在当前行之上新开一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Er\u003C/td\u003E\n\u003Ctd\u003E替换当前字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ER\u003C/td\u003E\n\u003Ctd\u003E替换当前字符及其后的字符，直至按ESC键\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Es\u003C/td\u003E\n\u003Ctd\u003E从当前光标位置处开始，以输入的文本替代指定数目的字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ES\u003C/td\u003E\n\u003Ctd\u003E删除指定数目的行，并以所输入文本代替之\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Encw或nCW\u003C/td\u003E\n\u003Ctd\u003E修改指定数目的字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EnCC\u003C/td\u003E\n\u003Ctd\u003E修改指定数目的行\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"3.1.6 删除命令","pId":"1a342f6","name":"3.1.6 删除命令","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987043,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"删除命令\" class=\"anchor\" href=\"#%E5%88%A0%E9%99%A4%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E删除命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Endw或ndW\u003C/td\u003E\n\u003Ctd\u003E删除光标处开始及其后的n-1个字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ed0\u003C/td\u003E\n\u003Ctd\u003E删至行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ed$\u003C/td\u003E\n\u003Ctd\u003E删至行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Endd\u003C/td\u003E\n\u003Ctd\u003E删除当前行及其后n-1行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ex或X\u003C/td\u003E\n\u003Ctd\u003E删除一个字符，x删除光标后的，而X删除光标前的\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+u\u003C/td\u003E\n\u003Ctd\u003E删除输入方式下所输入的文本\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"3.1.7 搜索及替换命令","pId":"1a342f6","name":"3.1.7 搜索及替换命令","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987044,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-搜索及替换命令\" class=\"anchor\" href=\"#1-%E6%90%9C%E7%B4%A2%E5%8F%8A%E6%9B%BF%E6%8D%A2%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 搜索及替换命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E/pattern\u003C/td\u003E\n\u003Ctd\u003E从光标开始处向文件尾搜索pattern\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E?pattern\u003C/td\u003E\n\u003Ctd\u003E从光标开始处向文件首搜索pattern\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En\u003C/td\u003E\n\u003Ctd\u003E在同一方向重复上一次搜索命令\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EN\u003C/td\u003E\n\u003Ctd\u003E在反方向上重复上一次搜索命令\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:s/p1/p2/g\u003C/td\u003E\n\u003Ctd\u003E将当前行中所有p1均用p2替代\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:%s/p1/p2/g\u003C/td\u003E\n\u003Ctd\u003E将所有p1均用p2替代\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2s/p1/p2/g\u003C/td\u003E\n\u003Ctd\u003E将第n1至n2行中所有p1均用p2替代\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:g/p1/s//p2/g\u003C/td\u003E\n\u003Ctd\u003E将文件中所有p1均用p2替换\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:%s+/str11/str12/+/str21/str22+\u003C/td\u003E\n\u003Ctd\u003E（使用+ 来 替换 / ）： /str11/str12/替换成/str21/str22/\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-替换demo\" class=\"anchor\" href=\"#2-%E6%9B%BF%E6%8D%A2demo\"\u003E\u003C/a\u003E2. 替换demo\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E将 /usr/local/deve/soft/redis 替换成 /usr/local/redis\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E%s+/deve/soft/+/+g  \n\u003C/code\u003E\u003C/pre\u003E"},{"id":"3.1.8 最后行方式命令","pId":"1a342f6","name":"3.1.8 最后行方式命令","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987045,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 co n3\u003C/td\u003E\n\u003Ctd\u003E将n1行到n2行之间的内容拷贝到第n3行下\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 m n3\u003C/td\u003E\n\u003Ctd\u003E将n1行到n2行之间的内容移至到第n3行下\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 d\u003C/td\u003E\n\u003Ctd\u003E将n1行到n2行之间的内容删除\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:w\u003C/td\u003E\n\u003Ctd\u003E保存当前文件\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:e filename\u003C/td\u003E\n\u003Ctd\u003E打开文件filename进行编辑\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:x\u003C/td\u003E\n\u003Ctd\u003E保存当前文件并退出\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:q\u003C/td\u003E\n\u003Ctd\u003E退出vi\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:q!\u003C/td\u003E\n\u003Ctd\u003E不保存文件并退出vi\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:!command\u003C/td\u003E\n\u003Ctd\u003E执行shell命令command\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 w!command\u003C/td\u003E\n\u003Ctd\u003E将文件中n1行至n2行的内容作为command的输入并执行之，若不指定n1，n2，则表示将整个文件内容作为command的输入\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:r!command\u003C/td\u003E\n\u003Ctd\u003E将命令command的输出结果放到当前行\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"3.1.9  寄存器操作","pId":"1a342f6","name":"3.1.9  寄存器操作","parent":"三、linux /03 常用命令/3.1 vi 命令","order":0,"sort_id":987046,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?nyy\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下n行的内容保存到寄存器？中，其中?为一个字母，n为一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?nyw\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下n个字保存到寄存器？中，其中?为一个字母，n为一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?nyl\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下n个字符保存到寄存器？中，其中?为一个字母，n为一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?p\u003C/td\u003E\n\u003Ctd\u003E取出寄存器？中的内容并将其放到光标位置处。这里？可以是一个字母，也可以是一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Endd\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下共n行文本删除，并将所删内容放到1号删除寄存器中。\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"ebcfc3b","pId":"8b32ab8","name":"3.2 权限命令","parent":"三、linux /03 常用命令","sort_id":987047,"order":0,"isParent":true,"extname":null,"open":false},{"id":"3.2.1 用户管理","pId":"ebcfc3b","name":"3.2.1 用户管理","parent":"三、linux /03 常用命令/3.2 权限命令","order":0,"sort_id":987048,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Col class=\"task-list\"\u003E\n\u003Cli\u003E创建用户\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E//创建monitor用户，用户id为501，所属组为monitor，附加群组为admin，起始目录为/monitor\nuseradd -u 501 -g monitor -G admin -d /monitor monitor\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-u:直接给出userID\u003C/li\u003E\n\u003Cli\u003E-g:指定用户所属的群组\u003C/li\u003E\n\u003Cli\u003E-G 指定用户所属的附加群组\u003C/li\u003E\n\u003Cli\u003E-d:指定用户登入时的启始目录\u003C/li\u003E\n\u003Cli\u003E-s:定义shell\u003C/li\u003E\n\u003C/ul\u003E\n\u003Col start=\"2\" class=\"task-list\"\u003E\n\u003Cli\u003E设置密码：\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003Epasswd fxz\n\n或者\n\necho \"123456\" | passwd --stdin fxz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"3\" class=\"task-list\"\u003E\n\u003Cli\u003E用户信息文件\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecat /etc/passwd\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"4\" class=\"task-list\"\u003E\n\u003Cli\u003E用户密码文件\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E/etc/shadow\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"5\" class=\"task-list\"\u003E\n\u003Cli\u003E用户组文件\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecat /etc/group\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"3.3 svn 命令","pId":"8b32ab8","name":"3.3 svn 命令","parent":"三、linux /03 常用命令","order":0,"sort_id":987051,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1将文件checkout到本地目录\" class=\"anchor\" href=\"#1%E5%B0%86%E6%96%87%E4%BB%B6checkout%E5%88%B0%E6%9C%AC%E5%9C%B0%E7%9B%AE%E5%BD%95\"\u003E\u003C/a\u003E1.将文件checkout到本地目录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn checkout path（path是服务器上的目录）\n例如：svn checkout svn://192.168.1.1/pro/domain\n简写：svn co\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2往版本库中添加新的文件\" class=\"anchor\" href=\"#2%E5%BE%80%E7%89%88%E6%9C%AC%E5%BA%93%E4%B8%AD%E6%B7%BB%E5%8A%A0%E6%96%B0%E7%9A%84%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E2.往版本库中添加新的文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn add file\n例如：svn add test.php(添加test.php)\nsvn add *.php(添加当前目录下所有的php文件)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3将改动的文件提交到版本库\" class=\"anchor\" href=\"#3%E5%B0%86%E6%94%B9%E5%8A%A8%E7%9A%84%E6%96%87%E4%BB%B6%E6%8F%90%E4%BA%A4%E5%88%B0%E7%89%88%E6%9C%AC%E5%BA%93\"\u003E\u003C/a\u003E3.将改动的文件提交到版本库\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn commit -m \"LogMessage\" [-N] [--no-unlock] PATH(如果选择了保持锁，就使用--no-unlock开关)\n例如：svn commit -m \"add test file for my test\" test.php\n简写：svn ci\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4加锁解锁\" class=\"anchor\" href=\"#4%E5%8A%A0%E9%94%81%E8%A7%A3%E9%94%81\"\u003E\u003C/a\u003E4.加锁/解锁\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn lock -m \"LockMessage\" [--force] PATH\n例如：svn lock -m \"lock test file\" test.php\nsvn unlock PATH\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5更新到某个版本\" class=\"anchor\" href=\"#5%E6%9B%B4%E6%96%B0%E5%88%B0%E6%9F%90%E4%B8%AA%E7%89%88%E6%9C%AC\"\u003E\u003C/a\u003E5.更新到某个版本\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn update -r m path\n例如：\nsvn update如果后面没有目录，默认将当前目录以及子目录下的所有文件都更新到最新版本。\nsvn update -r 200 test.php(将版本库中的文件test.php还原到版本200)\nsvn update test.php(更新，于版本库同步。如果在提交的时候提示过期的话，是因为冲突，需要先update，修改文件，然后清除svn resolved，最后再提交commit)\n简写：svn up\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6查看文件或者目录状态\" class=\"anchor\" href=\"#6%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6%E6%88%96%E8%80%85%E7%9B%AE%E5%BD%95%E7%8A%B6%E6%80%81\"\u003E\u003C/a\u003E6.查看文件或者目录状态\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1）svn status path（目录下的文件和子目录的状态，正常状态不显示）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E【?：不在svn的控制中；M：内容被修改；C：发生冲突；A：预定加入到版本库；K：被锁定】\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E2）svn status -v path(显示文件和子目录状态)\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E第一列保持相同，第二列显示工作版本号，第三和第四列显示最后一次修改的版本号和修改人。\n注：svn status.svn diff和 svn revert这三条命令在没有网络的情况下也可以执行的，原因是svn在本地的.svn中保留了本地版本的原始拷贝。\n简写：svn st\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"7删除文件\" class=\"anchor\" href=\"#7%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E7.删除文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn delete path -m \"delete test fle\"\n例如：svn delete svn://192.168.1.1/pro/domain/test.php -m \"delete test file\"\n或者直接svn delete test.php 然后再svn ci -m 'delete test file‘，推荐使用这种\n简写：svn (del, remove, rm)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"8查看日志\" class=\"anchor\" href=\"#8%E6%9F%A5%E7%9C%8B%E6%97%A5%E5%BF%97\"\u003E\u003C/a\u003E8.查看日志\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn log path\n例如：svn log test.php 显示这个文件的所有修改记录，及其版本号的变化\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"9查看文件详细信息\" class=\"anchor\" href=\"#9%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E9.查看文件详细信息\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn info path\n例如：svn info test.php\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"10比较差异\" class=\"anchor\" href=\"#10%E6%AF%94%E8%BE%83%E5%B7%AE%E5%BC%82\"\u003E\u003C/a\u003E10.比较差异\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn diff path(将修改的文件与基础版本比较)\n例如：svn diff test.php\nsvn diff -r m:n path(对版本m和版本n比较差异)\n例如：svn diff -r 200:201 test.php\n简写：svn di\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"11将两个版本之间的差异合并到当前文件\" class=\"anchor\" href=\"#11%E5%B0%86%E4%B8%A4%E4%B8%AA%E7%89%88%E6%9C%AC%E4%B9%8B%E9%97%B4%E7%9A%84%E5%B7%AE%E5%BC%82%E5%90%88%E5%B9%B6%E5%88%B0%E5%BD%93%E5%89%8D%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E11.将两个版本之间的差异合并到当前文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn merge -r m:n path\n例如：svn merge -r 200:205 test.php（将版本200与205之间的差异合并到当前文件，但是一般都会产生冲突，需要处理一下）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"12svn-帮助\" class=\"anchor\" href=\"#12svn-%E5%B8%AE%E5%8A%A9\"\u003E\u003C/a\u003E12.SVN 帮助\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn help\nsvn help ci\n\u003C/code\u003E\u003C/pre\u003E\n\u003Chr\u003E\n\u003Cp\u003E以上是常用命令，下面写几个不经常用的\u003C/p\u003E\n\u003Chr\u003E\n\u003Ch3\u003E\n\u003Ca id=\"13版本库下的文件和目录列表\" class=\"anchor\" href=\"#13%E7%89%88%E6%9C%AC%E5%BA%93%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E5%92%8C%E7%9B%AE%E5%BD%95%E5%88%97%E8%A1%A8\"\u003E\u003C/a\u003E13.版本库下的文件和目录列表\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn list path\n显示path目录下的所有属于版本库的文件和目录\n简写：svn ls\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"14创建纳入版本控制下的新目录\" class=\"anchor\" href=\"#14%E5%88%9B%E5%BB%BA%E7%BA%B3%E5%85%A5%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%B8%8B%E7%9A%84%E6%96%B0%E7%9B%AE%E5%BD%95\"\u003E\u003C/a\u003E14.创建纳入版本控制下的新目录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn mkdir: 创建纳入版本控制下的新目录。\n用法: 1.mkdir PATH...\n 2.mkdir URL...\n创建版本控制的目录。\n1.每一个以工作副本 PATH 指定的目录，都会创建在本地端，并且加入新增\n调度，以待下一次的提交。\n2.每个以URL指定的目录，都会透过立即提交于仓库中创建。\n在这两个情况下，所有的中间目录都必须事先存在。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"15恢复本地修改\" class=\"anchor\" href=\"#15%E6%81%A2%E5%A4%8D%E6%9C%AC%E5%9C%B0%E4%BF%AE%E6%94%B9\"\u003E\u003C/a\u003E15.恢复本地修改\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn revert: 恢复原始未改变的工作副本文件 (恢复大部份的本地修改)。revert:\n用法: revert PATH...\n注意: 本子命令不会存取网络，并且会解除冲突的状况。但是它不会恢复\n被删除的目录\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"16代码库url变更\" class=\"anchor\" href=\"#16%E4%BB%A3%E7%A0%81%E5%BA%93url%E5%8F%98%E6%9B%B4\"\u003E\u003C/a\u003E16.代码库URL变更\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn switch (sw): 更新工作副本至不同的URL。\n用法: 1.switch URL [PATH]\n2.switch --relocate FROM TO [PATH...]\n\n1.更新你的工作副本，映射到一个新的URL，其行为跟“svn update”很像，也会将\n服务器上文件与本地文件合并。这是将工作副本对应到同一仓库中某个分支或者标记的\n方法。\n2.改写工作副本的URL元数据，以反映单纯的URL上的改变。当仓库的根URL变动 \n(比如方案名或是主机名称变动)，但是工作副本仍旧对映到同一仓库的同一目录时使用\n这个命令更新工作副本与仓库的对应关系。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"17解决冲突\" class=\"anchor\" href=\"#17%E8%A7%A3%E5%86%B3%E5%86%B2%E7%AA%81\"\u003E\u003C/a\u003E17.解决冲突\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn resolved: 移除工作副本的目录或文件的“冲突”状态。\n用法: resolved PATH...\n注意: 本子命令不会依语法来解决冲突或是移除冲突标记；它只是移除冲突的\n相关文件，然后让 PATH 可以再次提交。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"18输出指定文件或url的内容\" class=\"anchor\" href=\"#18%E8%BE%93%E5%87%BA%E6%8C%87%E5%AE%9A%E6%96%87%E4%BB%B6%E6%88%96url%E7%9A%84%E5%86%85%E5%AE%B9\"\u003E\u003C/a\u003E18.输出指定文件或URL的内容。\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn cat 目标[@版本]...如果指定了版本，将从指定的版本开始查找。\nsvn cat -r PREV filename \u0026gt; filename (PREV 是上一版本,也可以写具体版本号,这样输出结果是可以提交的)\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"3.4 ps命令","pId":"8b32ab8","name":"3.4 ps命令","parent":"三、linux /03 常用命令","order":0,"sort_id":987052,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003El\u003C/td\u003E\n\u003Ctd\u003E长格式输出；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eu\u003C/td\u003E\n\u003Ctd\u003E按用户名和启动时间的顺序来显示进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ej\u003C/td\u003E\n\u003Ctd\u003E用任务格式来显示进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ef\u003C/td\u003E\n\u003Ctd\u003E用树形格式来显示进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ea\u003C/td\u003E\n\u003Ctd\u003E显示所有用户的所有进程（包括其它用户）；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ex\u003C/td\u003E\n\u003Ctd\u003E显示无控制终端的进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Er\u003C/td\u003E\n\u003Ctd\u003E显示运行中的进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eww\u003C/td\u003E\n\u003Ctd\u003E避免详细参数被截断；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-A\u003C/td\u003E\n\u003Ctd\u003E列出所有的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-w\u003C/td\u003E\n\u003Ctd\u003E显示加宽可以显示较多的资讯\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-au\u003C/td\u003E\n\u003Ctd\u003E显示较详细的资讯\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-aux\u003C/td\u003E\n\u003Ctd\u003E显示所有包含其他使用者的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-e\u003C/td\u003E\n\u003Ctd\u003E显示所有进程,环境变量\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-f\u003C/td\u003E\n\u003Ctd\u003E全格式\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-h\u003C/td\u003E\n\u003Ctd\u003E不显示标题\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-l\u003C/td\u003E\n\u003Ctd\u003E长格式\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-w\u003C/td\u003E\n\u003Ctd\u003E宽输出\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ea\u003C/td\u003E\n\u003Ctd\u003E显示终端上地所有进程,包括其他用户的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Er\u003C/td\u003E\n\u003Ctd\u003E只显示正在运行的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ex\u003C/td\u003E\n\u003Ctd\u003E显示没有控制终端的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E我们常用的选项是组合是 aux 或 lax，还有参数 f 的应用。\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"4.1 xlauch 服务器","pId":"54f3dd9","name":"4.1 xlauch 服务器","parent":"三、linux /04  服务器","order":0,"sort_id":987054,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-demoxlauchcom\" class=\"anchor\" href=\"#1-demoxlauchcom\"\u003E\u003C/a\u003E1. demo.xlauch.com\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/project/xlauch-web\u003C/li\u003E\n\u003Cli\u003Eredis启动命令：service redis start\u003C/li\u003E\n\u003Cli\u003Etomcat目录：/usr/soft/apache-tomcat-7.0.68\u003C/li\u003E\n\u003Cli\u003E启动命令：./startup.sh\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2wangmarket-建站系统\" class=\"anchor\" href=\"#2wangmarket-%E5%BB%BA%E7%AB%99%E7%B3%BB%E7%BB%9F\"\u003E\u003C/a\u003E2.wangmarket 建站系统\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/project/web-market\u003C/li\u003E\n\u003Cli\u003Etomcat目录：/usr/soft/apache-tomcat-8.5.31\u003C/li\u003E\n\u003Cli\u003E启动命令：./startup.sh\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3frp\" class=\"anchor\" href=\"#3frp\"\u003E\u003C/a\u003E3.frp\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/local/frp_0.17.0_linux_amd64/\u003C/li\u003E\n\u003Cli\u003E启动命令：setsid ./frps -c frps.ini\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4nginx\" class=\"anchor\" href=\"#4nginx\"\u003E\u003C/a\u003E4.Nginx\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/etc/nginx/\u003C/li\u003E\n\u003Cli\u003E启动命令：service nginx start\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5erueka-server\" class=\"anchor\" href=\"#5erueka-server\"\u003E\u003C/a\u003E5.erueka-server\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E工程目录：/etc/nginx/\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E启动命令：\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Enohup java -jar eurekaserver-0.0.1-SNAPSHOT.jar --spring.profiles.active=9081 \u0026gt;\u0026gt; /usr/project/logs/eureka/9081 .log 2\u0026gt;\u0026amp;1 \u0026amp;\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Enohup java -jar eurekaserver-0.0.1-SNAPSHOT.jar --spring.profiles.active=9082 \u0026gt;\u0026gt; /usr/project/logs/eureka/9082.log 2\u0026gt;\u0026amp;1 \u0026amp;\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6gogs\" class=\"anchor\" href=\"#6gogs\"\u003E\u003C/a\u003E6.gogs\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/local/gogs/\u003C/li\u003E\n\u003Cli\u003E启动命令：nohup ./gogs web \u0026amp;\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"5.1.1. jvm 结构","pId":"008a6af","name":"5.1.1. jvm 结构","parent":"五、java 虚拟机/01 JVM 结构","order":0,"sort_id":995807,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://blog.csdn.net/bruce128/article/details/79357870\"\u003EJDK1.8 JVM运行时数据区域划分\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-结构图\" class=\"anchor\" href=\"#2-%E7%BB%93%E6%9E%84%E5%9B%BE\"\u003E\u003C/a\u003E2. 结构图\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1115/103136_453d4438_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"21-类加载子系统\" class=\"anchor\" href=\"#21-%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%AD%90%E7%B3%BB%E7%BB%9F\"\u003E\u003C/a\u003E2.1. 类加载子系统\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E负责从文件或者网络中加载class信息，加载的信息存放在方法区\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"22-方法区\" class=\"anchor\" href=\"#22-%E6%96%B9%E6%B3%95%E5%8C%BA\"\u003E\u003C/a\u003E2.2. 方法区\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E存放类信息、常量信息、常量池信息、包括字符串字常量和数字常量\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"23-java堆\" class=\"anchor\" href=\"#23-java%E5%A0%86\"\u003E\u003C/a\u003E2.3. JAVA堆\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ejava程序最主要的内存工作区域，几乎所有的对象实例都存在java堆中，堆空间是所有线程共享\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"24-直接内存\" class=\"anchor\" href=\"#24-%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98\"\u003E\u003C/a\u003E2.4. 直接内存\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ejava的NIO库允许java程序使用直接内存，从而提高性能，通常直接内存速度会优于java堆。读写频繁的场合可能会考虑使用\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"25-java栈\" class=\"anchor\" href=\"#25-java%E6%A0%88\"\u003E\u003C/a\u003E2.5. JAVA栈\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E每个虚拟机线程都有一个私有的栈，用于保存局部变量、方法参数、方法调用的返回值等\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"26-本地方法栈\" class=\"anchor\" href=\"#26-%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%B3%95%E6%A0%88\"\u003E\u003C/a\u003E2.6. 本地方法栈\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E用于本地方法调用（通常使用C编写）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"27-pc寄存器\" class=\"anchor\" href=\"#27-pc%E5%AF%84%E5%AD%98%E5%99%A8\"\u003E\u003C/a\u003E2.7. PC寄存器\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E每个线程私有空间，用于存放当前执行环境指针、程序计数器、操作栈指针\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"28-gc垃圾回收\" class=\"anchor\" href=\"#28-gc%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6\"\u003E\u003C/a\u003E2.8. GC垃圾回收\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E开发人员无需手工清理\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"29-执行引擎\" class=\"anchor\" href=\"#29-%E6%89%A7%E8%A1%8C%E5%BC%95%E6%93%8E\"\u003E\u003C/a\u003E2.9. 执行引擎\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E负责执行虚拟机的字节码，一般用户先进行编译成机器码后执行\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"1.1 配置SSL 证书","pId":"8676f23","name":"1.1 配置SSL 证书","parent":"八、框架/01 springboot","order":0,"sort_id":1164286,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://blog.csdn.net/gary_yan/article/details/77981303\"\u003Ehttps的SSL证书在服务器端的部署\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-tomcat下配置\" class=\"anchor\" href=\"#2-tomcat%E4%B8%8B%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E2. tomcat下配置\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Connector port=\"18443\"\n\t\tprotocol=\"HTTP/1.1\"\n\t\tSSLEnabled=\"true\"\n\t\tscheme=\"https\"\n\t\tsecure=\"true\"\n\t\tkeystoreFile=\"E:/deve/tools/apache-tomcat-8.5.31/cert/cert-1541639405263_fxz.xlauch.com.pfx\"\n\t\tkeystoreType=\"PKCS12\"\n\t\tkeystorePass=\"FWhJH4TX\"\n\t\tclientAuth=\"false\"\n\t\tSSLProtocol=\"TLSv1+TLSv1.1+TLSv1.2\"\n\t\tciphers=\"TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256\"/\u0026gt;\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-springboot-配置\" class=\"anchor\" href=\"#3-springboot-%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3. springboot 配置\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eserver.port = 18443 \n\nserver.ssl.key-store=classpath:cert-1541639405263_fxz.xlauch.com.pfx\nserver.ssl.key-store-password=FWhJH4TX\nserver.ssl.keyStoreType=PKCS12\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1219/105753_6c6c1f2a_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"26c49d2","pId":"c21f20d","name":"02 springboot-dubbo","parent":"八、框架","sort_id":1340229,"order":0,"isParent":true,"extname":null,"open":false},{"id":"2.1 入门","pId":"26c49d2","name":"2.1 入门","parent":"八、框架/02 springboot-dubbo","order":0,"sort_id":1340230,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Cp\u003E官网地址：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"http://dubbo.apache.org/zh-cn/\"\u003Ehttp://dubbo.apache.org/zh-cn/\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003Egit 地址：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://github.com/apache/incubator-dubbo-spring-boot-project/blob/master/README_CN.md\"\u003Ehttps://github.com/apache/incubator-dubbo-spring-boot-project/blob/master/README_CN.md\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1-创建demo工程\" class=\"anchor\" href=\"#1-%E5%88%9B%E5%BB%BAdemo%E5%B7%A5%E7%A8%8B\"\u003E\u003C/a\u003E1. 创建demo工程\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E目录结构如下：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2019/0227/152222_ab951636_907621.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Epom.xml 配置版本信息：\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n\u0026lt;project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u0026gt;\n    \u0026lt;modelVersion\u0026gt;4.0.0\u0026lt;/modelVersion\u0026gt;\n\n    \u0026lt;groupId\u0026gt;dubbo-sb-demo\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;com.xlauch.dubbo\u0026lt;/artifactId\u0026gt;\n    \u0026lt;packaging\u0026gt;pom\u0026lt;/packaging\u0026gt;\n    \u0026lt;version\u0026gt;1.0-SNAPSHOT\u0026lt;/version\u0026gt;\n\n\n    \u0026lt;modules\u0026gt;\n        \u0026lt;module\u0026gt;dubbo-sb-demo-api\u0026lt;/module\u0026gt;\n        \u0026lt;module\u0026gt;dubbo-sb-demo-consumer\u0026lt;/module\u0026gt;\n        \u0026lt;module\u0026gt;dubbo-sb-demo-provider\u0026lt;/module\u0026gt;\n    \u0026lt;/modules\u0026gt;\n\n    \u0026lt;properties\u0026gt;\n        \u0026lt;java.version\u0026gt;1.8\u0026lt;/java.version\u0026gt;\n        \u0026lt;project.build.sourceEncoding\u0026gt;UTF-8\u0026lt;/project.build.sourceEncoding\u0026gt;\n        \u0026lt;project.reporting.outputEncoding\u0026gt;UTF-8\u0026lt;/project.reporting.outputEncoding\u0026gt;\n\n        \u0026lt;springboot-version\u0026gt;2.0.2.RELEASE\u0026lt;/springboot-version\u0026gt;\n        \u0026lt;dubbo-springboot-version\u0026gt;0.2.0\u0026lt;/dubbo-springboot-version\u0026gt;\n        \u0026lt;zkclient.version\u0026gt;0.9\u0026lt;/zkclient.version\u0026gt;\n    \u0026lt;/properties\u0026gt;\n\n\u0026lt;/project\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-api工程\" class=\"anchor\" href=\"#2-api%E5%B7%A5%E7%A8%8B\"\u003E\u003C/a\u003E2. api工程\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E声明接口\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/3/7\n */\npublic interface HelloService {\n\n    /**\n     * hello\n     * @param name\n     * @return\n     */\n    public String sayHello(String name) ;\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-实现-dubbo-服务提供方\" class=\"anchor\" href=\"#2-%E5%AE%9E%E7%8E%B0-dubbo-%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9\"\u003E\u003C/a\u003E2. 实现 Dubbo 服务提供方\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) pom.xml 依赖\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n\u0026lt;project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u0026gt;\n    \u0026lt;parent\u0026gt;\n        \u0026lt;artifactId\u0026gt;com.xlauch.dubbo\u0026lt;/artifactId\u0026gt;\n        \u0026lt;groupId\u0026gt;dubbo-sb-demo\u0026lt;/groupId\u0026gt;\n        \u0026lt;version\u0026gt;1.0-SNAPSHOT\u0026lt;/version\u0026gt;\n    \u0026lt;/parent\u0026gt;\n    \u0026lt;modelVersion\u0026gt;4.0.0\u0026lt;/modelVersion\u0026gt;\n\n    \u0026lt;artifactId\u0026gt;dubbo-sb-demo-provider\u0026lt;/artifactId\u0026gt;\n\n    \u0026lt;dependencies\u0026gt;\n        \u0026lt;!-- 本地api dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;${project.groupId}\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-sb-demo-api\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${project.version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- Spring Boot dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-web\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-actuator\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- dubbo dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-starter\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-actuator\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- zookeeper dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.101tec\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;zkclient\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${zkclient.version}\u0026lt;/version\u0026gt;\n            \u0026lt;exclusions\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-api\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;log4j\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;log4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-log4j12\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n            \u0026lt;/exclusions\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n\n    \u0026lt;/dependencies\u0026gt;\n\n    \u0026lt;dependencyManagement\u0026gt;\n        \u0026lt;dependencies\u0026gt;\n            \u0026lt;dependency\u0026gt;\n                \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n                \u0026lt;artifactId\u0026gt;spring-boot-starter-parent\u0026lt;/artifactId\u0026gt;\n                \u0026lt;version\u0026gt;${springboot-version}\u0026lt;/version\u0026gt;\n                \u0026lt;type\u0026gt;pom\u0026lt;/type\u0026gt;\n                \u0026lt;scope\u0026gt;import\u0026lt;/scope\u0026gt;\n            \u0026lt;/dependency\u0026gt;\n        \u0026lt;/dependencies\u0026gt;\n    \u0026lt;/dependencyManagement\u0026gt;\n\n    \u0026lt;repositories\u0026gt;\n        \u0026lt;repository\u0026gt;\n            \u0026lt;id\u0026gt;sonatype-nexus-snapshots\u0026lt;/id\u0026gt;\n            \u0026lt;url\u0026gt;https://oss.sonatype.org/content/repositories/snapshots\u0026lt;/url\u0026gt;\n            \u0026lt;releases\u0026gt;\n                \u0026lt;enabled\u0026gt;false\u0026lt;/enabled\u0026gt;\n            \u0026lt;/releases\u0026gt;\n            \u0026lt;snapshots\u0026gt;\n                \u0026lt;enabled\u0026gt;true\u0026lt;/enabled\u0026gt;\n            \u0026lt;/snapshots\u0026gt;\n        \u0026lt;/repository\u0026gt;\n    \u0026lt;/repositories\u0026gt;\n\u0026lt;/project\u0026gt;\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E注意：zookeeper移除log4j相关包\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(2) 实现接口\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.dubbo.demo.consumer.service;\n\n\nimport com.alibaba.dubbo.config.annotation.Service;\nimport com.xlauch.dubbo.demo.api.service.HelloService;\nimport com.xlauch.dubbo.demo.api.pojo.User;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@Service(\n        version = \"${demo.service.version}\",\n        application = \"${dubbo.application.id}\",\n        protocol = \"${dubbo.protocol.id}\",\n        registry = \"${dubbo.registry.id}\"\n)\npublic class HelloServiceImpl implements HelloService {\n\n    @Override\n    public String sayHello(String name) {\n        return \"hello水电费 : \" + name;\n    }\n\n    @Override\n    public String addUser(User user) {\n        return user.toString();\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(3) 编写 Spring Boot 启动类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@SpringBootApplication\npublic class DubboProviderDemo {\n\n    public static void main(String[] args) {\n\n        new SpringApplicationBuilder(DubboProviderDemo.class)\n                .web(false) // 非 Web 应用\n                .run(args);\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(4) 配置 application.properties\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# Spring boot application\nspring.application.name=dubbo-provider-demo\nserver.port=9090\nmanagement.server.port=9091\n\n# Service version\ndemo.service.version=1.0.0\n# Base packages to scan Dubbo Components (e.g @Service , @Reference)\ndubbo.scan.basePackages=com.xlauch.dubbo.demo.consumer.service\n\n# Dubbo Config properties\n## ApplicationConfig Bean\ndubbo.application.id=dubbo-provider-demo\ndubbo.application.name=dubbo-provider-demo\n\n## ProtocolConfig Bean\ndubbo.protocol.id=dubbo\ndubbo.protocol.name=dubbo\ndubbo.protocol.port=12345\n\n## RegistryConfig Bean\ndubbo.registry.id=my-registry\ndubbo.registry.address=zookeeper://127.0.0.1:2181\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-实现-dubbo-服务消费方\" class=\"anchor\" href=\"#3-%E5%AE%9E%E7%8E%B0-dubbo-%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E6%96%B9\"\u003E\u003C/a\u003E3. 实现 Dubbo 服务消费方\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) pom.xml 依赖\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n\u0026lt;project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u0026gt;\n    \u0026lt;parent\u0026gt;\n        \u0026lt;artifactId\u0026gt;com.xlauch.dubbo\u0026lt;/artifactId\u0026gt;\n        \u0026lt;groupId\u0026gt;dubbo-sb-demo\u0026lt;/groupId\u0026gt;\n        \u0026lt;version\u0026gt;1.0-SNAPSHOT\u0026lt;/version\u0026gt;\n    \u0026lt;/parent\u0026gt;\n    \u0026lt;modelVersion\u0026gt;4.0.0\u0026lt;/modelVersion\u0026gt;\n\n    \u0026lt;artifactId\u0026gt;dubbo-sb-demo-consumer\u0026lt;/artifactId\u0026gt;\n    \u0026lt;dependencies\u0026gt;\n        \u0026lt;!-- 本地api dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;${project.groupId}\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-sb-demo-api\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${project.version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- Spring Boot dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-web\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-actuator\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- dubbo dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-starter\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-actuator\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- zookeeper dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.101tec\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;zkclient\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${zkclient.version}\u0026lt;/version\u0026gt;\n            \u0026lt;exclusions\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-api\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;log4j\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;log4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-log4j12\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n            \u0026lt;/exclusions\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n\n    \u0026lt;/dependencies\u0026gt;\n\n    \u0026lt;dependencyManagement\u0026gt;\n        \u0026lt;dependencies\u0026gt;\n            \u0026lt;dependency\u0026gt;\n                \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n                \u0026lt;artifactId\u0026gt;spring-boot-starter-parent\u0026lt;/artifactId\u0026gt;\n                \u0026lt;version\u0026gt;${springboot-version}\u0026lt;/version\u0026gt;\n                \u0026lt;type\u0026gt;pom\u0026lt;/type\u0026gt;\n                \u0026lt;scope\u0026gt;import\u0026lt;/scope\u0026gt;\n            \u0026lt;/dependency\u0026gt;\n        \u0026lt;/dependencies\u0026gt;\n    \u0026lt;/dependencyManagement\u0026gt;\n\n\u0026lt;/project\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) 通过 @Reference 注入 HelloService\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.dubbo.demo.consumer.controller;\n\n\nimport com.alibaba.dubbo.config.annotation.Reference;\nimport com.xlauch.dubbo.demo.api.service.HelloService;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@RestController\npublic class HelloController {\n\n    @Reference(version = \"${demo.service.version}\",\n            application = \"${dubbo.application.id}\",\n            timeout = 3000)\n    private HelloService helloService;\n\n    @RequestMapping(\"/sayHello\")\n    public String sayHello(@RequestParam String name) {\n        return helloService.sayHello(name);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(2) 编写 Spring Boot 启动类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.dubbo.demo.consumer;\n\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@SpringBootApplication\npublic class DubboConsumerDemo {\n\n    public static void main(String[] args) {\n\n        SpringApplication.run(DubboConsumerDemo.class, args);\n\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(3) 配置 application.properties\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# Spring boot application\nspring.application.name = dubbo-consumer-demo\nserver.port = 8080\nmanagement.server.port = 8081\n\n# Service Version\ndemo.service.version = 1.0.0\n\n# Dubbo Config properties\n## ApplicationConfig Bean\ndubbo.application.id = dubbo-consumer-demo\ndubbo.application.name = dubbo-consumer-demo\n\n## ProtocolConfig Bean\ndubbo.protocol.id = dubbo\ndubbo.protocol.name = dubbo\ndubbo.protocol.port = 12345\n\ndubbo.registry.id=my-registry\ndubbo.registry.address=zookeeper://127.0.0.1:2181\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"ed9af11","pId":"d1f6d69","name":"1.1 Redis 命令","parent":"四、数据库/01 redis","sort_id":995584,"order":0,"isParent":true,"extname":null,"open":false},{"id":"1.1.1 redis ","pId":"ed9af11","name":"1.1.1 redis ","parent":"四、数据库/01 redis/1.1 Redis 命令","order":0,"sort_id":988113,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"http://doc.redisfans.com/\"\u003ERedis 命令参考\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.runoob.com/redis/redis-tutorial.html\"\u003ERedis 教程\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/152223_3f674bf9_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"1.2.3.2 集群常见问题","pId":"c07e325","name":"1.2.3.2 集群常见问题","parent":"四、数据库/01 redis/1.2 redis 高级/1.2.3 集群","order":0,"sort_id":1047311,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-redis-requires-ruby-version--222问题\" class=\"anchor\" href=\"#1-redis-requires-ruby-version--222%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E1. redis requires Ruby version \u0026gt;= 2.2.2问题\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 1.安装curl\n\nsudo yum install curl\n\n\n# 2. 设置公钥\n\ngpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB\n\n# 3. 安装RVM\n\ncurl -L get.rvm.io | bash -s stable \n \nsource /usr/local/rvm/scripts/rvm\n\n# 4. 查看rvm库中已知的ruby版本\n\nrvm list known\n\n# 5. 安装一个ruby版本\n\nrvm install 2.4.4\n\n# 6. 使用一个ruby版本\n\nrvm use 2.4.4\n\n# 7. 设置默认版本\n\nrvm remove 2.0.0\n\n# 8. 卸载一个已知版本\n\nruby --version\n\n# 9. 再安装redis就可以了\n\ngem install redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-redis-集群-创建报错-err-node-is-not-empty-either-the-node-already-knows-other-nodes\" class=\"anchor\" href=\"#2-redis-%E9%9B%86%E7%BE%A4-%E5%88%9B%E5%BB%BA%E6%8A%A5%E9%94%99-err-node-is-not-empty-either-the-node-already-knows-other-nodes\"\u003E\u003C/a\u003E2. redis 集群 创建报错 [ERR] Node is not empty. Either the node already knows other nodes\u003C/h3\u003E\n\u003Col class=\"task-list\"\u003E\n\u003Cli\u003E将每个节点下aof、rdb、nodes.conf本地备份文件删除；\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E mv nodes-700*.conf ./bak/\n mv appendonly.aof ./bak/\n mv dump.rdb ./bak/\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"2\" class=\"task-list\"\u003E\n\u003Cli\u003E172.168.63.201:7001\u0026gt; flushdb #清空当前数据库(可省略)\u003C/li\u003E\n\u003Cli\u003E之后再执行脚本，成功执行；\u003C/li\u003E\n\u003C/ol\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-redis-cluster-warning-node-1270017003-has-slots-in-migrating-state-15495\" class=\"anchor\" href=\"#3-redis-cluster-warning-node-1270017003-has-slots-in-migrating-state-15495\"\u003E\u003C/a\u003E3. Redis Cluster [WARNING] Node 127.0.0.1:7003 has slots in migrating state (15495).\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E解决办法2：登入提示错误的两个节点执行以下清除命令\n\ncluster setslot 15495 stable\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"cd26332","pId":"83ae707","name":"02 oracle","parent":"四、数据库","sort_id":1129821,"order":0,"isParent":true,"extname":null,"open":false},{"id":"7e4f1cd","pId":"83ae707","name":"03 mysql","parent":"四、数据库","sort_id":1135911,"order":0,"isParent":true,"extname":null,"open":false},{"id":"1.2 class 锁","pId":"2fc41b2","name":"1.2 class 锁","parent":"一、并发编程/01  线程基础","order":1,"sort_id":679019,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo静态static-synchronized-变成class-锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E9%9D%99%E6%80%81static-synchronized-%E5%8F%98%E6%88%90class-%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo（静态static synchronized 变成class 锁）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.base.sync002;\n\n/**\n * 关键字synchronized取得的锁都是对象锁，而不是把一段代码（方法）当做锁，\n * 所以代码中哪个线程先执行synchronized关键字的方法，哪个线程就持有该方法所属对象的锁（Lock），\n * \u0026lt;p\u0026gt;\n * 在静态方法上加synchronized关键字，表示锁定.class类，类一级别的锁（独占.class类）。\n *\n * @author alienware\n */\npublic class MultiThread {\n\n    private int num = 0;\n\n    /**\n     * static\n     */\n    public synchronized void printNum(String tag) {\n        try {\n\n            if (tag.equals(\"a\")) {\n                num = 100;\n                System.out.println(\"tag a, set num over!\");\n                Thread.sleep(1000);\n            } else {\n                num = 200;\n                System.out.println(\"tag b, set num over!\");\n            }\n\n            System.out.println(\"tag \" + tag + \", num = \" + num);\n\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n\n    /**\n     * 注意观察run方法输出顺序\n     *\n     * @param args\n     */\n    public static void main(String[] args) {\n\n        //俩个不同的对象\n        final MultiThread m1 = new MultiThread();\n        final MultiThread m2 = new MultiThread();\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                m1.printNum(\"a\");\n            }\n        });\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                m2.printNum(\"b\");\n            }\n        });\n\n        t1.start();\n        t2.start();\n\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"printNum\"方法不加static时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/095201_b13ac50e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"printNum\"方法加上static时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/095233_f14f5e61_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-案例说明\" class=\"anchor\" href=\"#2-%E6%A1%88%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 案例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关键字synchronized取得的锁都是对象锁\u003C/li\u003E\n\u003Cli\u003E在静态方法上加synchronized关键字，表示锁定.class类，类一级别的锁（独占.class类）。\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"77fbb9c","pId":"f417e8e","name":"02 多线程通信","parent":"一、并发编程","sort_id":686206,"order":1,"isParent":true,"extname":null,"open":false},{"id":"2.2 单例与多线程","pId":"77fbb9c","name":"2.2 单例与多线程","parent":"一、并发编程/02 多线程通信","order":1,"sort_id":688448,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"多线程下单例解决方案\" class=\"anchor\" href=\"#%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8B%E5%8D%95%E4%BE%8B%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88\"\u003E\u003C/a\u003E多线程下单例解决方案\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E方案1：多次确认\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class DubbleSingleton {\n\n\tprivate static DubbleSingleton ds;\n\t\n\tpublic  static DubbleSingleton getDs(){\n\t\tif(ds == null){\n\t\t\ttry {\n\t\t\t\t//模拟初始化对象的准备时间...\n\t\t\t\tThread.sleep(3000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\tsynchronized (DubbleSingleton.class) {\n\t\t\t\tif(ds == null){\n\t\t\t\t\tds = new DubbleSingleton();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ds;\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSystem.out.println(DubbleSingleton.getDs().hashCode());\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSystem.out.println(DubbleSingleton.getDs().hashCode());\n\t\t\t}\n\t\t},\"t2\");\n\t\tThread t3 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSystem.out.println(DubbleSingleton.getDs().hashCode());\n\t\t\t}\n\t\t},\"t3\");\n\t\t\n\t\tt1.start();\n\t\tt2.start();\n\t\tt3.start();\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E同步块中，一定要再次验证：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esynchronized (DubbleSingleton.class) {\n     if(ds == null){\n\tds = new DubbleSingleton();\n     }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E方案2：内部类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Singletion {\n\t\n\tprivate static class InnerSingletion {\n\t\tprivate static Singletion single = new Singletion();\n\t}\n\t\n\tpublic static Singletion getInstance(){\n\t\treturn InnerSingletion.single;\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.4.2 模拟Queue","pId":"75d372a","name":"2.4.2 模拟Queue","parent":"一、并发编程/02 多线程通信/2.4 高并发容器","order":1,"sort_id":688445,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Queue {\n\n    /**\n     * 1 创建一个集合，存储对象\n     */\n    private static LinkedList\u0026lt;Object\u0026gt; list = new LinkedList\u0026lt;Object\u0026gt;();\n\n\n    /**\n     * 2 计数\n     */\n    private AtomicInteger count = new AtomicInteger(0);\n\n    /**\n     * 3 定义存储上限、下限\n     */\n    private int maxSize = 5;\n\n    private int minSize = 0;\n\n    /**\n     * 4 创建构造\n     *\n     * @param maxSize\n     */\n    public Queue(int maxSize) {\n        this.maxSize = maxSize;\n    }\n\n    /**\n     * 5 定义锁对象\n     */\n    private Object lock = new Object();\n\n\n    /**\n     * 存入对象\n     *\n     * @param object\n     */\n    public void put(Object object) {\n        synchronized (lock) {\n            if (count.get() == this.maxSize) {\n                try {\n                    lock.wait();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }\n\n\n            list.add(object);\n            count.incrementAndGet();\n            lock.notify();\n            System.out.println(\"存入对象: \" + object);\n        }\n    }\n\n\n    /**\n     * 获取对象\n     *\n     * @return\n     */\n    public Object get() {\n        Object ret = null ;\n        synchronized (lock){\n            if (count.get() == this.minSize){\n                try {\n                    lock.wait();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }\n\n            ret = list.removeFirst();\n            count.decrementAndGet();\n            lock.notify();\n            System.out.println(\"获取对象：\" + ret);\n        }\n        return ret ;\n    }\n\n\n    public static void  main(String[] args) {\n        final Queue queue = new Queue(5);\n\n        queue.put(\"a\");\n        queue.put(\"b\");\n        queue.put(\"c\");\n        queue.put(\"d\");\n        queue.put(\"e\");\n\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                queue.put(\"f\");\n                queue.put(\"g\");\n            }\n        }).start();\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                queue.get();\n                try {\n                    Thread.sleep(1000);\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n                queue.get();\n            }\n        }).start();\n    }\n\n\n}\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.5.2 Executor、Executors","pId":"b6b90b0","name":"2.5.2 Executor、Executors","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":1,"sort_id":731113,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-executor\" class=\"anchor\" href=\"#1-executor\"\u003E\u003C/a\u003E1. Executor\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EJava线程池的超级接口；提供一个execute(Runnable command)方法;我们一般用它的继承接口ExecutorService。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-executorservice它是线程池定义的一个接口继承executor有两个实现类分别为threadpoolexecutorscheduledthreadpoolexecutor\" class=\"anchor\" href=\"#2-executorservice%E5%AE%83%E6%98%AF%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%AE%9A%E4%B9%89%E7%9A%84%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BFexecutor%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%E5%88%86%E5%88%AB%E4%B8%BAthreadpoolexecutorscheduledthreadpoolexecutor\"\u003E\u003C/a\u003E2. ExecutorService：它是线程池定义的一个接口，继承Executor。有两个实现类，分别为ThreadPoolExecutor,ScheduledThreadPoolExecutor。\u003C/h4\u003E\n\u003Cp\u003E线程池的继承树：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0906/151553_f286d769_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-executorservice常用的几个方法\" class=\"anchor\" href=\"#3-executorservice%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E4%B8%AA%E6%96%B9%E6%B3%95\"\u003E\u003C/a\u003E3. ExecutorService常用的几个方法：\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eexecute(Runnable)：方法接收一个Runnable实例，并且异步的执行\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo1 {\n    \n    public static void main(String[] args) {\n        ExecutorService executorService = Executors.newSingleThreadExecutor(); //创建一个单线程\n        executorService.execute(new Runnable() { //接收一个Runnable实例\n            public void run() {\n                System.out.println(\"Asynchronous task\");\n            }\n        });\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esubmit(Runnable)：返回一个Future对象，通过返回的Future对象，我们可以检查提交的任务是否执行完毕\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo2 {\n    \n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor(); //创建一个单线程\n        Future future = executorService.submit(new Runnable() { //接收一个Runnable实例\n            public void run() {\n                System.out.println(\"Asynchronous task\");\n            }\n        });\n        System.out.println(future.get()); //任务执行结束返回null.\n        executorService.shutdown();\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esubmit(Callable)：与submit(Callable)类似，也会返回一个Future对象，但是除此之外，submit(Callable)接收的是一个Callable的实现，Callable接口中的call()方法有一个返回值，可以返回任务的执行结果，而Runnable接口中的run()方法是void的，没有返回值\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo1 {\n    \n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor(); //创建一个单线程\n        Future\u0026lt;Object\u0026gt; future = executorService.submit(new Callable\u0026lt;Object\u0026gt;() { //接收一个Callable实例\n            public Object call() {\n                System.out.println(\"Asynchronous task\");\n                return \"Callable Result\";\n            }\n        });\n        System.out.println(\"future.get()=\"+future.get());\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EinvokeAny(...)：方法接收的是一个Callable的集合，执行这个方法不会返回Future，但是会返回所有Callable任务中其中一个任务的执行结果。这个方法也无法保证返回的是哪个任务的执行结果，反正是其中的某一个。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo2 {\n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Set\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt; callables = new HashSet\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt;();\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result1\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result2\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result3\";\n            }\n            \n        });\n        \n        String result = executorService.invokeAny(callables);        \n        System.out.println(result);\n        executorService.shutdown();\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EinvokeAll(...)：与 invokeAny(...)类似也是接收一个Callable集合，但是前者执行之后会返回一个Future的List，其中对应着每个Callable任务执行后的Future对象。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo3 {\n\n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Set\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt; callables = new HashSet\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt;();\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result1\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result2\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result3\";\n            }\n            \n        });\n        \n        List\u0026lt;Future\u0026lt;String\u0026gt;\u0026gt; futures = executorService.invokeAll(callables);    //返回一个Future的List集合    \n        for(Future\u0026lt;String\u0026gt; future:futures){\n            System.out.println(\"future.get()=\"+future.get());\n        }\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eshutdown()：我们使用完成ExecutorService之后应该关闭它，否则它里面的线程会一直处于运行状态。\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.6.2 CyclicBarrier","pId":"3b56f09","name":"2.6.2 CyclicBarrier","parent":"一、并发编程/02 多线程通信/2.6 concurrent工具类","order":1,"sort_id":736292,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Random;\nimport java.util.concurrent.BrokenBarrierException;\nimport java.util.concurrent.CyclicBarrier;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/10\n */\npublic class TestCyclicBarrier {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    /**\n     * 国家测试类\n     */\n    static class Country implements Runnable {\n        private CyclicBarrier barrier;\n\n        private String name;\n\n        Country(CyclicBarrier barrier, String name) {\n            this.barrier = barrier;\n            this.name = name;\n        }\n\n        @Override\n        public void run() {\n            System.out.println(FORMAT.format(new Date()) +  name + \" 开始准备...\");\n            try {\n                Thread.sleep(new Random().nextInt(3000));\n                barrier.await();\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            } catch (BrokenBarrierException e) {\n                e.printStackTrace();\n            }\n\n            System.out.println(FORMAT.format(new Date()) + \"=======================\" + name + \" 准备结束...\");\n        }\n    }\n\n    public static void main(String[] args) {\n        final CyclicBarrier barrier = new CyclicBarrier(5);\n\n        ExecutorService executorService = Executors.newFixedThreadPool(5);\n        executorService.execute(new Country(barrier, \"中国\"));\n        executorService.execute(new Country(barrier, \"美国\"));\n        executorService.execute(new Country(barrier, \"英国\"));\n        executorService.execute(new Country(barrier, \"法国\"));\n        executorService.execute(new Country(barrier, \"小日本\"));\n\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003ECyclicBarrier 的字面意思是可循环使用（Cyclic）的屏障（Barrier）。它要做的事情是，让一组线程到达一个屏障（也可以叫同步点）时被阻塞，直到最后一个线程到达屏障时，屏障才会开门，所有被屏障拦截的线程才会继续干活。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003ECyclicBarrier默认的构造方法是CyclicBarrier(int parties)，其参数表示屏障拦截的线程数量，每个线程调用await方法告诉CyclicBarrier我已经到达了屏障，然后当前线程被阻塞。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003ECyclicBarrier强调的是n个线程，大家相互等待，只要有一个没完成，所有人都得等着。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-cyclicbarrier和countdownlatch的区别\" class=\"anchor\" href=\"#3-cyclicbarrier%E5%92%8Ccountdownlatch%E7%9A%84%E5%8C%BA%E5%88%AB\"\u003E\u003C/a\u003E3. CyclicBarrier和CountDownLatch的区别\u003C/h3\u003E\n\u003Cp\u003E（1）CountDownLatch的计数器只能使用一次。而CyclicBarrier的计数器可以使用reset() 方法重置。所以CyclicBarrier能处理更为复杂的业务场景，比如如果计算发生错误，可以重置计数器，并让线程们重新执行一次。\u003C/p\u003E\n\u003Cp\u003E（2）CyclicBarrier还提供其他有用的方法，比如getNumberWaiting方法可以获得CyclicBarrier阻塞的线程数量。isBroken方法用来知道阻塞的线程是否被中断。比如以下代码执行完之后会返回true。\u003C/p\u003E\n\u003Cp\u003E（3）CountDownLatch会阻塞主线程，CyclicBarrier不会阻塞主线程，只会阻塞子线程。\u003C/p\u003E"},{"id":"2.7.2 Condition使用","pId":"5fc2e0f","name":"2.7.2 Condition使用","parent":"一、并发编程/02 多线程通信/2.7 Lock 锁","order":1,"sort_id":799824,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.height.lock020.fxz;\n\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/25\n */\npublic class TestLockCondition {\n\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n\n    /**\n     * 定义锁\n     */\n    private Lock lock = new ReentrantLock();\n\n    /**\n     * 定义锁条件\n     */\n    private Condition condition1 = lock.newCondition();\n\n    private Condition condition2 = lock.newCondition();\n\n\n    /**\n     * 等待方法\n     */\n    public void doWait() {\n        try {\n            lock.lock();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"进入等待\");\n            condition1.await();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"继续\");\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n    /**\n     * 等待方法\n     */\n    public void doWait2() {\n        try {\n            lock.lock();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"进入等待\");\n            condition2.await();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"继续\");\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n\n\n    /**\n     * 唤醒方法\n     */\n    public void doNotify() {\n        try {\n            lock.lock();\n            Thread.sleep(1000);\n            condition1.signalAll();\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void doNotify2() {\n        try {\n            lock.lock();\n            Thread.sleep(1000);\n            condition2.signal();\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n    public static void main(String[] args) throws InterruptedException {\n\n        final TestLockCondition test = new TestLockCondition();\n        /**\n         * 多线程执行，需要等上一线程执行完成，下一个线程才能开始\n         */\n        for (int i = 0; i \u0026lt; 3; i++) {\n            new Thread(() -\u0026gt; {\n                test.doWait();\n            }, \"t\" + i).start();\n        }\n\n\n        Thread.sleep(1000);\n        System.out.println(\"============================\");\n        new Thread(() -\u0026gt; {\n            test.doWait2();\n        }, \"t3\" ).start();\n\n        Thread.sleep(2000);\n        System.out.println(\"============================唤醒前三个线程\");\n        test.doNotify();\n\n        new Thread(() -\u0026gt; {\n            test.doNotify2();\n        }, \"t4\" ).start();\n    }\n\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0926/110346_d9fe103d_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Econdition必须结合Lock对象一起使用\u003C/li\u003E\n\u003Cli\u003E多个condition互不影响\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.8.1 HelloWorld","pId":"6619c4c","name":"2.8.1 HelloWorld","parent":"一、并发编程/02 多线程通信/2.8 disruptor","order":1,"sort_id":820044,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1定义evenet类\" class=\"anchor\" href=\"#1%E5%AE%9A%E4%B9%89evenet%E7%B1%BB\"\u003E\u003C/a\u003E1、定义Evenet类\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEvent {\n\n    private int id;\n\n    private String name;\n\n    public UserEvent(){\n    }\n\n    public UserEvent(int id , String name) {\n        this.id = id ;\n        this.name = name;\n    }\n\n    @Override\n    public String toString() {\n        return \"UserEvent{\" +\n                \"id=\" + id +\n                \", name='\" + name + '\\'' +\n                '}';\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2定义eventfactory\" class=\"anchor\" href=\"#2%E5%AE%9A%E4%B9%89eventfactory\"\u003E\u003C/a\u003E2、定义EventFactory\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.EventFactory;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventFactory implements EventFactory {\n\n    @Override\n    public Object newInstance() {\n        return new UserEvent();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E3、定义事件句柄（事件消费者）\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.EventHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventHandler implements EventHandler\u0026lt;UserEvent\u0026gt; {\n\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(UserEvent userEvent, long l, boolean b) throws Exception {\n        System.out.println(FORMAT.format(new Date()) +  userEvent);\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4定义eventproducer\" class=\"anchor\" href=\"#4%E5%AE%9A%E4%B9%89eventproducer\"\u003E\u003C/a\u003E4、定义EventProducer\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventProducer {\n\n    private RingBuffer\u0026lt;UserEvent\u0026gt; ringBuffer ;\n\n    public UserEventProducer(RingBuffer\u0026lt;UserEvent\u0026gt; ringBuffer) {\n        this.ringBuffer = ringBuffer ;\n    }\n\n\n    public void onData(UserEvent userEvent) {\n        // 1. 获取下一个可用序号\n        long sequence = ringBuffer.next() ;\n\n        try {\n            // 2. 获取缓存中的对象\n            UserEvent temp = ringBuffer.get(sequence);\n            // 3. 赋值对象\n            temp.setId(userEvent.getId());\n            temp.setName(userEvent.getName());\n        }catch (Exception e){\n            e.printStackTrace();\n        } finally {\n            // 4. 发布\n            ringBuffer.publish(sequence);\n        }\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1、 获取下一个可用序号\u003C/li\u003E\n\u003Cli\u003E2、 获取缓存中的对象\u003C/li\u003E\n\u003Cli\u003E3、 赋值对象\u003C/li\u003E\n\u003Cli\u003E4、 发布\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5测试\" class=\"anchor\" href=\"#5%E6%B5%8B%E8%AF%95\"\u003E\u003C/a\u003E5、测试\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.RingBuffer;\nimport com.lmax.disruptor.YieldingWaitStrategy;\nimport com.lmax.disruptor.dsl.Disruptor;\nimport com.lmax.disruptor.dsl.ProducerType;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventMain {\n\n    public static void main(String[] args) {\n        long start = System.currentTimeMillis() ;\n\n        // 创建线程池\n        ExecutorService executor = Executors.newCachedThreadPool();\n\n        // 创建事件工厂\n        UserEventFactory eventFactory = new UserEventFactory();\n\n        // 指定ringbuffer大小 ，必须是2的N次方\n        int ringBufferSize = 1024 * 1024;\n\n        /**\n         * 创建disruptor\n         * @param eventFactory      ： 创建事件工厂\n         * @param ringBufferSize    ： ringbuffer大小 ，必须是2的N次方\n         * @param executor          : 线程池\n         * @param producerType      : 生产者类型\n         *                                  ProducerType.SINGLE：单个生产者\n         *                                  ProducerType.MULTI: 多个生产者\n         * @param waitStrategy      : 等待策略\n         *                                  BlockingWaitStrategy 是最低效的策略，但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现\n         *                                  SleepingWaitStrategy 的性能表现跟BlockingWaitStrategy差不多，对CPU的消耗也类似，但其对生产者线程的影响最小，适合用于异步日志类似的场景\n         *                                  YieldingWaitStrategy 的性能是最好的，适合用于低延迟的系统。在要求极高性能且事件处理线数小于CPU逻辑核心数的场景中，推荐使用此策略；例如，CPU开启超线程的特性\n         */\n        Disruptor\u0026lt;UserEvent\u0026gt; disruptor = new Disruptor\u0026lt;UserEvent\u0026gt;(eventFactory, ringBufferSize, executor, ProducerType.SINGLE, new YieldingWaitStrategy());\n\n        // 连接消费事件方法\n        disruptor.handleEventsWith(new UserEventHandler());\n\n        // 启动\n        disruptor.start();\n\n        // 发布事件\n        publish(disruptor.getRingBuffer());\n\n        // 关闭 disruptor，方法会堵塞，直至所有的事件都得到处理；\n        disruptor.shutdown();\n\n        // 关闭 disruptor 使用的线程池；如果需要的话，必须手动关闭， disruptor 在 shutdown 时不会自动关闭；\n        executor.shutdown();\n\n        System.out.println(\"耗时：\" + (System.currentTimeMillis() - start) + \"ms\");\n    }\n\n    /**\n     * 发布事件\n     * @param ringBuffer\n     */\n    private static void publish(RingBuffer\u0026lt;UserEvent\u0026gt; ringBuffer) {\n        UserEventProducer producer = new UserEventProducer(ringBuffer);\n        int count = 600 * 10000 ;\n        for (int i = 1 ; i \u0026lt;= count ; i++) {\n            producer.onData(new UserEvent(i , \"name_\" + i));\n        }\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"91330e0","pId":"3119987","name":"01 docker","parent":"七、容器、集成","sort_id":1094081,"order":1,"isParent":true,"extname":null,"open":false},{"id":"Docker中容器无法停止无法删除","pId":"91330e0","name":"Docker中容器无法停止无法删除","parent":"七、容器、集成/01 docker","order":1,"sort_id":1094082,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Cp\u003EDocker 容器镜像删除\u003C/p\u003E\n\u003Cp\u003E1.停止所有的容器\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Edocker stop $(docker ps -q)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E2.强制移除此容器\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Edocker rm -f mysql1\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E3.清理此容器的网络占用\u003C/p\u003E\n\u003Cp\u003E格式：docker network disconnect --force 网络模式 容器名称\u003C/p\u003E\n\u003Cp\u003E示例：docker network disconnect --force bridge mysql1\u003C/p\u003E\n\u003Cp\u003E4.简查是否还有同名容器占用\u003C/p\u003E\n\u003Cp\u003E格式：docker network inspect 网络模式\n示例：docker network inspect bridge\u003C/p\u003E\n\u003Cp\u003E5.重新构建容器\u003C/p\u003E\n\u003Cp\u003Edocker run --name mysql1 -d -p3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:latest\u003C/p\u003E\n\u003Cp\u003E1.停止所有的container，这样才能够删除其中的images：\u003C/p\u003E\n\u003Cp\u003Edocker stop $(docker ps -a -q)\u003C/p\u003E\n\u003Cp\u003E如果想要删除所有container的话再加一个指令：\u003C/p\u003E\n\u003Cp\u003Edocker rm $(docker ps -a -q)\u003C/p\u003E\n\u003Cp\u003E2.查看当前有些什么images\u003C/p\u003E\n\u003Cp\u003Edocker images\u003C/p\u003E\n\u003Cp\u003E3.删除images，通过image的id来指定删除谁\u003C/p\u003E\n\u003Cp\u003Edocker rmi \u003C/p\u003E\n\u003Cp\u003E想要删除untagged images，也就是那些id为的image的话可以用\u003C/p\u003E\n\u003Cp\u003Edocker rmi $(docker images | grep \"^\" | awk \"{print $3}\")\u003C/p\u003E\n\u003Cp\u003E要删除全部image的话\u003C/p\u003E\n\u003Cp\u003Edocker rmi $(docker images -q)\u003C/p\u003E"},{"id":"1.2 安装Tomcat","pId":"7a86ec7","name":"1.2 安装Tomcat","parent":"三、linux /01 软件安装","order":1,"sort_id":987023,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-安装准备\" class=\"anchor\" href=\"#1-%E5%AE%89%E8%A3%85%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E1. 安装准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E首先从官网上下载\u003Ca href=\"https://tomcat.apache.org/download-80.cgi\"\u003E tomcat8 \u003C/a\u003E\n\u003C/li\u003E\n\u003Cli\u003E解压：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf apache-tomcat-8.5.30.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动tomcat\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd bin\n./startup.sh\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-配置多个tomcat\" class=\"anchor\" href=\"#2-%E9%85%8D%E7%BD%AE%E5%A4%9A%E4%B8%AAtomcat\"\u003E\u003C/a\u003E2. 配置多个tomcat\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E远程停服务端口，默认8005，如下改为8006\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Server port=\"8006\" shutdown=\"SHUTDOWN\"\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EHTTP端口，默认8080，如下改为8081\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E其中8081为HTTP端口，8443为HTTPS端口\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Connector port=\"8081\" protocol=\"HTTP/1.1\"   \n               connectionTimeout=\"60000\"   \n               redirectPort=\"8443\" disableUploadTimeout=\"false\"  executor=\"tomcatThreadPool\"  URIEncoding=\"UTF-8\"/\u0026gt;  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EAJP端口，默认8009，如下改,8010\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Connector port=\"8010\" protocol=\"AJP/1.3\" redirectPort=\"8443\" /\u0026gt;  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-配置不同的jdk\" class=\"anchor\" href=\"#3-%E9%85%8D%E7%BD%AE%E4%B8%8D%E5%90%8C%E7%9A%84jdk\"\u003E\u003C/a\u003E3. 配置不同的JDK\u003C/h3\u003E\n\u003Cp\u003E修改tomcat环境变量有三种方法：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E第一种：定义在全局里；如果装有多个JDK的话，定义全局会冲突，不建议\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E第二种：写用户家目录下的环境变量文件.bash_profile\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E第三种：是定义在单个tomcat的启动和关闭程序里，建议使用这种\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@Tomcat ~]# vim /usr/local/tomcat/bin/startup.sh              --tomcat的启动程序\n[root@Tomcat ~]# vim /usr/local/tomcat/bin/shutdown.sh             --tomcat的关闭程序\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E把startup.sh和shutdown.sh这两个脚本里的最前面加上下面一段：\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eexport JAVA_HOME=/usr/local/java\nexport TOMCAT_HOME=/usr/local/tomcat\nexport CATALINA_HOME=/usr/local/tomcat\nexport CLASS_PATH=$JAVA_HOME/bin/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tool.jar\nexport PATH=$PATH:/usr/local/java/bin:/usr/local/tomcat/bin\n\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"6275c3c","pId":"2116d9f","name":"02 系统操作","parent":"三、linux ","sort_id":987031,"order":1,"isParent":true,"extname":null,"open":false},{"id":"2.2 xmanager 链接centos6","pId":"6275c3c","name":"2.2 xmanager 链接centos6","parent":"三、linux /02 系统操作","order":1,"sort_id":987033,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E编辑/etc/gdm/custom.conf文件并保存退出(允许root用户通过177端口远程访问xdmcp桌面服务):\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@vm205 ~]# cp /etc/gdm/custom.conf /etc/gdm/custom.conf.bak\n[root@vm205 ~]# vi /etc/gdm/custom.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003E----------在[xdmcp]选项下添加如下一行内容----------\nEnable=true\nPort=177\n----------在[security]选项下添加如下一行内容------\nAllowRemoteRoot=true\n------------------------------------------------\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E查看刚才修改内容\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@vm205 ~]# grep -Ev '^#' /etc/gdm/custom.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E重启gdm服务(在Linux6系统中没有gdm-restart之类的命令了---注意区别):\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ereboot\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"3.5 tar 命令","pId":"8b32ab8","name":"3.5 tar 命令","parent":"三、linux /03 常用命令","order":1,"sort_id":1137948,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1压缩\" class=\"anchor\" href=\"#1%E5%8E%8B%E7%BC%A9\"\u003E\u003C/a\u003E1.压缩\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E打包成xxx.tar（即tarfile）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -cvf xxx.tar xxx ... (多个目录)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar进行打包压缩成xxx.tar.gz\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zcvf xxx.tar.gz xxx ...(多个目录)　　\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-解包\" class=\"anchor\" href=\"#2-%E8%A7%A3%E5%8C%85\"\u003E\u003C/a\u003E2. 解包\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解包xxx.tar\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -xvf xxx.tar\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar解压缩xxx.tar.gz文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf xxx.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar解压缩xxx.tar.gz文件到指定的目录(该目录需已经存在)\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf xxx.tar.gz -C destdir\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar解压缩xxx.tar.gz中某个文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf xxx.tar.gz aaa/bbb\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-查看压缩包内的内容\" class=\"anchor\" href=\"#3-%E6%9F%A5%E7%9C%8B%E5%8E%8B%E7%BC%A9%E5%8C%85%E5%86%85%E7%9A%84%E5%86%85%E5%AE%B9\"\u003E\u003C/a\u003E3. 查看压缩包内的内容\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -ztvf xxx.tar.gz\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1. 批量生成缩略图","pId":"97a5782","name":"1. 批量生成缩略图","parent":"九、工具类","order":1,"sort_id":1174238,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.ext.face.excel;\n\nimport com.sun.image.codec.jpeg.JPEGImageEncoder;\nimport com.sun.image.codec.jpeg.JPEGCodec;\nimport com.sun.image.codec.jpeg.JPEGEncodeParam;\n\nimport javax.imageio.ImageIO;\nimport java.awt.image.BufferedImage;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.FileOutputStream;\n\npublic class ResizeImage {\n\n    private final static SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    /**\n     * @param im            原始图像\n     * @param resizeTimes   需要缩小的倍数，缩小2倍为原来的1/2 ，这个数值越大，返回的图片越小\n     * @return              返回处理后的图像\n     */\n    public BufferedImage resizeImage(BufferedImage im, float resizeTimes) {\n        /*原始图像的宽度和高度*/\n        int width = im.getWidth();\n        int height = im.getHeight();\n\n        /*调整后的图片的宽度和高度*/\n        int toWidth = (int) (Float.parseFloat(String.valueOf(width)) / resizeTimes);\n        int toHeight = (int) (Float.parseFloat(String.valueOf(height)) / resizeTimes);\n\n        /*新生成结果图片*/\n        BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);\n\n        result.getGraphics().drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);\n        return result;\n    }\n\n    /**\n     * @param im            原始图像\n     * @param resizeTimes   倍数,比如0.5就是缩小一半,0.98等等double类型\n     * @return              返回处理后的图像\n     */\n    public BufferedImage zoomImage(BufferedImage im, float resizeTimes) {\n        /*原始图像的宽度和高度*/\n        int width = im.getWidth();\n        int height = im.getHeight();\n\n        /*调整后的图片的宽度和高度*/\n        int toWidth = (int) (Float.parseFloat(String.valueOf(width)) * resizeTimes);\n        int toHeight = (int) (Float.parseFloat(String.valueOf(height)) * resizeTimes);\n\n        /*新生成结果图片*/\n        BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);\n\n        result.getGraphics().drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);\n        return result;\n    }\n\n    /**\n     * @param path  要转化的图像的文件夹,就是存放图像的文件夹路径\n     * @param type  图片的后缀名组成的数组\n     * @return\n     */\n    public List\u0026lt;BufferedImage\u0026gt; getImageList(String path, String[] type) throws IOException{\n        Map\u0026lt;String,Boolean\u0026gt; map = new HashMap\u0026lt;String, Boolean\u0026gt;();\n        for(String s : type) {\n            map.put(s,true);\n        }\n        List\u0026lt;BufferedImage\u0026gt; result = new ArrayList\u0026lt;BufferedImage\u0026gt;();\n        File[] fileList = new File(path).listFiles();\n        for (File f : fileList) {\n            if(f.length() == 0)\n                continue;\n            if(map.get(getExtension(f.getName())) == null)\n                continue;\n            result.add(javax.imageio.ImageIO.read(f));\n        }\n        return result;\n    }\n\n    /**\n     * 把图片写到磁盘上\n     * @param im\n     * @param path     eg: C://home// 图片写入的文件夹地址\n     * @param fileName DCM1987.jpg  写入图片的名字\n     * @return\n     */\n    public boolean writeToDisk(BufferedImage im, String path, String fileName) {\n        File f = new File(path + fileName);\n        String fileType = getExtension(fileName);\n        if (fileType == null)\n            return false;\n        try {\n            ImageIO.write(im, fileType, f);\n            im.flush();\n            return true;\n        } catch (IOException e) {\n            return false;\n        }\n    }\n\n\n    public boolean writeHighQuality(BufferedImage im, String fileFullPath) {\n        try {\n            /*输出到文件流*/\n            FileOutputStream newimage = new FileOutputStream(fileFullPath+System.currentTimeMillis()+\".jpg\");\n            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(newimage);\n            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(im);\n            /* 压缩质量 */\n            jep.setQuality(1f, true);\n            encoder.encode(im, jep);\n            /*近JPEG编码*/\n            newimage.close();\n            return true;\n        } catch (Exception e) {\n            return false;\n        }\n    }\n\n    /**\n     * 返回文件的文件后缀名\n     * @param fileName\n     * @return\n     */\n    public String getExtension(String fileName) {\n        try {\n            return fileName.split(\"\\\\.\")[fileName.split(\"\\\\.\").length - 1];\n        } catch (Exception e) {\n            return null;\n        }\n    }\n\n    public static void main(String[] args) throws Exception{\n\n        long start = System.currentTimeMillis();\n\n        /*这儿填写你存放要缩小图片的文件夹全地址*/\n        String inputFoler = \"D:\\\\5i84\\\\2018\\\\人脸识别\\\\人脸照片\\\\采集原图\\\\12-19\";\n\n        /*这儿填写你转化后的图片存放的文件夹*/\n        String outputFolder = \"D:\\\\5i84\\\\2018\\\\人脸识别\\\\人脸照片\\\\采集原图\\\\12-19\\\\outPut\\\\1\";\n\n\n        /*这个参数是要转化成的倍数,如果是1就是转化成1倍*/\n        float times = 0.05f;\n\n\n        ResizeImage r = new ResizeImage();\n        List\u0026lt;BufferedImage\u0026gt; imageList = r.getImageList(inputFoler,new String[] {\"jpg\"});\n        for(BufferedImage i : imageList) {\n            r.writeHighQuality(r.zoomImage(i,times),outputFolder);\n        }\n\n        System.out.println(\"处理结束：\" + FORMAT.format(new Date()) + \"  耗时：\" + (System.currentTimeMillis() - start) / 1000 + \"s\");\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"5a10a14","pId":0,"name":"二、socket 编程","parent":"","sort_id":831352,"order":1,"isParent":true,"extname":null,"open":false},{"id":"8d337a8","pId":"5a10a14","name":"01 Socket 基础","parent":"二、socket 编程","sort_id":831355,"order":1,"isParent":true,"extname":null,"open":false},{"id":"1.1 socket 入门","pId":"8d337a8","name":"1.1 socket 入门","parent":"二、socket 编程/01 Socket 基础","order":1,"sort_id":831356,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EServer 端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.io.IOException;\nimport java.net.ServerSocket;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class Server {\n\n\n    public static void main(String[] args) {\n\n        ServerSocket serverSocket = null;\n\n        try {\n            serverSocket = new ServerSocket(Constants.PORT);\n            System.out.println(\"======================  服务启动  =======================\");\n            Socket socket = serverSocket.accept();\n\n            /**\n             * 单独启动线程处理\n             */\n//            new Thread(new SocketHandler(socket)).start();\n\n            /**\n             * 利用线程池处理\n             */\n            HandlerExecutorPool executorPool = new HandlerExecutorPool(100, 20);\n            executorPool.execute(new SocketHandler(socket));\n\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            SocketUtils.close(serverSocket);\n        }\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ESocketHandler\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.PrintWriter;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class SocketHandler implements Runnable {\n\n    private Socket socket;\n\n    public SocketHandler(Socket socket) {\n        this.socket = socket;\n    }\n\n    @Override\n    public void run() {\n        BufferedReader reader = null;\n        PrintWriter writer = null;\n\n        try {\n            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));\n            writer = new PrintWriter(socket.getOutputStream(), true);\n\n            String msg = null;\n            while (true) {\n                msg = reader.readLine();\n                if (msg == null) {\n                    break;\n                }\n\n                System.out.println(\"接收到信息： \" + msg);\n                writer.println(\"服务器端回送响的应数据.\");\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            SocketUtils.close(reader, writer, socket);\n        }\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EClient 端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.PrintWriter;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class Client {\n\n    public static void  main(String[] args) {\n\n        Socket socket = null ;\n        BufferedReader reader = null;\n        PrintWriter writer = null;\n\n        try {\n            socket = new Socket(Constants.HOST , Constants.PORT);\n            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));\n            writer = new PrintWriter(socket.getOutputStream(), true);\n\n\n            writer.println(\"客户端发送信息: 123\");\n\n            String msg = null ;\n            while (true) {\n                msg = reader.readLine();\n                if (msg == null) {\n                    break;\n                }\n                System.out.println(\"客户端收到信息:\" + msg);\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            SocketUtils.close(reader, writer, socket);\n        }\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E线程池方式处理\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/18\n */\npublic class HandlerExecutorPool {\n\n    private ExecutorService executorService;\n\n    public HandlerExecutorPool(int maxSize, int queueSize) {\n        this.executorService = new ThreadPoolExecutor(\n                Runtime.getRuntime().availableProcessors() - 1,\n                            maxSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue\u0026lt;\u0026gt;(queueSize));\n    }\n\n\n    public void execute(Runnable runnable) {\n        this.executorService.execute(runnable);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ESocketUtils\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.net.ServerSocket;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class SocketUtils {\n\n\n    /**\n     * 关闭资源\n     *\n     * @param reader\n     * @param writer\n     * @param socket\n     */\n    public static void close(BufferedReader reader, PrintWriter writer, Socket socket) {\n        if (reader != null) {\n            try {\n                reader.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n        if (writer != null) {\n            try {\n                writer.close();\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        if (socket != null) {\n            try {\n                socket.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n\n        socket = null;\n    }\n\n    public static void close(ServerSocket serverSocket) {\n        if (serverSocket != null) {\n            try {\n                serverSocket.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n\n        serverSocket = null;\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EConstants\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Constants {\n\n    public static final String HOST = \"127.0.0.1\";\n\n    public static final int PORT = 8333;\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-说明\" class=\"anchor\" href=\"#2-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用线程池可以减少服务器开销\u003C/li\u003E\n\u003Cli\u003E三次握手过程：\n\u003Col class=\"task-list\"\u003E\n\u003Cli\u003EserverSocket 启动监听\u003C/li\u003E\n\u003Cli\u003Eclient 发起连接\u003C/li\u003E\n\u003Cli\u003Eserver 确认连接\u003C/li\u003E\n\u003Cli\u003Eclient 确认连接\u003C/li\u003E\n\u003Cli\u003EC/S 通信\u003C/li\u003E\n\u003C/ol\u003E\n\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"5.1.2 堆结构","pId":"008a6af","name":"5.1.2 堆结构","parent":"五、java 虚拟机/01 JVM 结构","order":1,"sort_id":996034,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"java-堆\" class=\"anchor\" href=\"#java-%E5%A0%86\"\u003E\u003C/a\u003EJAVA 堆\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1115/105158_15c413f4_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1老年代三分之二的堆空间\" class=\"anchor\" href=\"#1%E8%80%81%E5%B9%B4%E4%BB%A3%E4%B8%89%E5%88%86%E4%B9%8B%E4%BA%8C%E7%9A%84%E5%A0%86%E7%A9%BA%E9%97%B4\"\u003E\u003C/a\u003E1、老年代：三分之二的堆空间\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E老生代采用的回收算法是标记整理算法\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2新生代--三分之一的堆空间\" class=\"anchor\" href=\"#2%E6%96%B0%E7%94%9F%E4%BB%A3--%E4%B8%89%E5%88%86%E4%B9%8B%E4%B8%80%E7%9A%84%E5%A0%86%E7%A9%BA%E9%97%B4\"\u003E\u003C/a\u003E2、新生代 ： 三分之一的堆空间\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eeden区： 8/10 的年轻代空间\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Esurvivor0 : 1/10 的年轻代空间\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Esurvivor1 : 1/10 的年轻代空间\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E新生代的回收机制采用复制算法，当我们的对象时长超过一定年龄时（默认15，可以通过参数设置），将会把对象放入老生代\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E对象刚实例化出来的时候分配在eden区\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E在一次新生代回收后，如果对象还存活，则会进入S0或S1区，之后每进过一次新生代回收，如果对象存活则他的回收次数就会加1\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当回收次数达到一定阈值时，则进入老年代\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3参数配置\" class=\"anchor\" href=\"#3%E5%8F%82%E6%95%B0%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3、参数配置\u003C/h4\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E作用\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:InitialSurvivorRatio\u003C/td\u003E\n\u003Ctd\u003E新生代Eden/Survivor空间的初始比例\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:Newratio\u003C/td\u003E\n\u003Ctd\u003EOld区 和 Yong区 的内存比例\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"5.2.1 回收算法","pId":"8cf0d42","name":"5.2.1 回收算法","parent":"五、java 虚拟机/02 垃圾回收","order":1,"sort_id":1013230,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-算法介绍\" class=\"anchor\" href=\"#1-%E7%AE%97%E6%B3%95%E4%BB%8B%E7%BB%8D\"\u003E\u003C/a\u003E1. 算法介绍\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E引用计数法：引用计数+1，失去引用-1；这种方法有一严重问题：无法处理循环引用情况，每次加减会浪费系统性能\u003C/li\u003E\n\u003Cli\u003E标记清除法：分标记和清除两个步骤，最大弊端是回收后导致内存空间不连续\u003C/li\u003E\n\u003Cli\u003E标记压缩法：在标记清除法的基础上，把存活对象压缩到内存的一端（老年代的垃圾回收算法）\u003C/li\u003E\n\u003Cli\u003E复制算法：把存活的对象复制到另外一块区域，然后清除原先的区域（新生代的垃圾回收算法）\u003C/li\u003E\n\u003Cli\u003E分代\u003C/li\u003E\n\u003Cli\u003E分区\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-为啥新生代与老年代的算法不一致\" class=\"anchor\" href=\"#2-%E4%B8%BA%E5%95%A5%E6%96%B0%E7%94%9F%E4%BB%A3%E4%B8%8E%E8%80%81%E5%B9%B4%E4%BB%A3%E7%9A%84%E7%AE%97%E6%B3%95%E4%B8%8D%E4%B8%80%E8%87%B4\"\u003E\u003C/a\u003E2. 为啥新生代与老年代的算法不一致\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E新生代回收频率高、对象不稳定，每次GC耗时短\u003C/li\u003E\n\u003Cli\u003E新生代回收的对象比较多\u003C/li\u003E\n\u003Cli\u003E老年代的对象是经过多次GC存活下来的，可能是长期存活的，回收频率低，耗时长，应尽量减少老年代的GC\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/093326_c9101443_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/095614_b2a2aaea_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/102011_c965df0e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/110141_a5a54c6b_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"1.2 打包","pId":"8676f23","name":"1.2 打包","parent":"八、框架/01 springboot","order":1,"sort_id":1165108,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-单独jar\" class=\"anchor\" href=\"#1-%E5%8D%95%E7%8B%ACjar\"\u003E\u003C/a\u003E1. 单独jar\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;plugins\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;spring-boot-maven-plugin\u0026lt;/artifactId\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n\u0026lt;/plugins\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-资源lib分开\" class=\"anchor\" href=\"#2-%E8%B5%84%E6%BA%90lib%E5%88%86%E5%BC%80\"\u003E\u003C/a\u003E2. 资源、lib分开\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;build\u0026gt;\n      \n\n\u0026lt;finalName\u0026gt;face\u0026lt;/finalName\u0026gt;\n\u0026lt;resources\u0026gt;\n    \u0026lt;resource\u0026gt;\n\t\u0026lt;directory\u0026gt;src/main/resources\u0026lt;/directory\u0026gt;\n    \u0026lt;/resource\u0026gt;\n    \u0026lt;resource\u0026gt;\n\t\u0026lt;directory\u0026gt;src/main/webapp\u0026lt;/directory\u0026gt;\n    \u0026lt;/resource\u0026gt;\n\u0026lt;/resources\u0026gt;\n\n\u0026lt;plugins\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-compiler-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t    \u0026lt;source\u0026gt;${java.version}\u0026lt;/source\u0026gt;\n\t    \u0026lt;target\u0026gt;${java.version}\u0026lt;/target\u0026gt;\n\t    \u0026lt;encoding\u0026gt;UTF-8\u0026lt;/encoding\u0026gt;\n\t\u0026lt;/configuration\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;org.apache.maven.plugins\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-dependency-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t    \u0026lt;execution\u0026gt;\n\t\t\u0026lt;id\u0026gt;copy-dependencies\u0026lt;/id\u0026gt;\n\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\u0026lt;goals\u0026gt;\n\t\t    \u0026lt;goal\u0026gt;copy-dependencies\u0026lt;/goal\u0026gt;\n\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;configuration\u0026gt;\n\t\t    \u0026lt;outputDirectory\u0026gt;${project.build.directory}/lib\u0026lt;/outputDirectory\u0026gt;\n\t\t\u0026lt;/configuration\u0026gt;\n\t    \u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n    \u0026lt;!-- 打成jar包 --\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-jar-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t    \u0026lt;excludes\u0026gt;\n\t\t\u0026lt;exclude\u0026gt;**/*.properties\u0026lt;/exclude\u0026gt;\n\t\t\u0026lt;exclude\u0026gt;**/pages/**\u0026lt;/exclude\u0026gt;\n\t\t\u0026lt;exclude\u0026gt;**/static/**\u0026lt;/exclude\u0026gt;\n\t    \u0026lt;/excludes\u0026gt;\n\t    \u0026lt;archive\u0026gt;\n\t\t\u0026lt;manifest\u0026gt;\n\t\t    \u0026lt;addClasspath\u0026gt;true\u0026lt;/addClasspath\u0026gt;\n\t\t    \u0026lt;classpathPrefix\u0026gt;lib/\u0026lt;/classpathPrefix\u0026gt;\n\t\t    \u0026lt;!--指明main方法所在的类 --\u0026gt;\n\t\t    \u0026lt;mainClass\u0026gt;com.xlauch.ext.face.FaceDetectApplication\u0026lt;/mainClass\u0026gt;\n\t\t    \u0026lt;useUniqueVersions\u0026gt;false\u0026lt;/useUniqueVersions\u0026gt;\n\t\t\u0026lt;/manifest\u0026gt;\n\t\t\u0026lt;manifestEntries\u0026gt;\n\t\t    \u0026lt;Class-Path\u0026gt;config/\u0026lt;/Class-Path\u0026gt;\n\t\t\u0026lt;/manifestEntries\u0026gt;\n\t    \u0026lt;/archive\u0026gt;\n\t\u0026lt;/configuration\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n    \u0026lt;!-- 处理资源文件 --\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;org.apache.maven.plugins\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-resources-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;version\u0026gt;2.4\u0026lt;/version\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t    \u0026lt;execution\u0026gt;\n\t\t\u0026lt;id\u0026gt;copy-resources\u0026lt;/id\u0026gt;\n\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\u0026lt;goals\u0026gt;\n\t\t    \u0026lt;goal\u0026gt;copy-resources\u0026lt;/goal\u0026gt;\n\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;configuration\u0026gt;\n\t\t    \u0026lt;encoding\u0026gt;utf-8\u0026lt;/encoding\u0026gt;\n\t\t    \u0026lt;outputDirectory\u0026gt;${project.build.directory}/config\u0026lt;/outputDirectory\u0026gt;\n\t\t    \u0026lt;!--把配置文件拷到/etc路径下 --\u0026gt;\n\t\t    \u0026lt;resources\u0026gt;\n\t\t\t\u0026lt;resource\u0026gt;\n\t\t\t    \u0026lt;directory\u0026gt;src/main/resources/\u0026lt;/directory\u0026gt;\n\t\t\t    \u0026lt;includes\u0026gt;\n\t\t\t\t\u0026lt;include\u0026gt;**/*.properties\u0026lt;/include\u0026gt;\n\t\t\t    \u0026lt;/includes\u0026gt;\n\t\t\t\u0026lt;/resource\u0026gt;\n\t\t\t\u0026lt;resource\u0026gt;\n\t\t\t    \u0026lt;directory\u0026gt;src/main/webapp/\u0026lt;/directory\u0026gt;\n\t\t\t    \u0026lt;includes\u0026gt;\n\t\t\t\t\u0026lt;include\u0026gt;**/pages/**\u0026lt;/include\u0026gt;\n\t\t\t\t\u0026lt;include\u0026gt;**/static/**\u0026lt;/include\u0026gt;\n\t\t\t    \u0026lt;/includes\u0026gt;\n\t\t\t\u0026lt;/resource\u0026gt;\n\t\t    \u0026lt;/resources\u0026gt;\n\t\t\u0026lt;/configuration\u0026gt;\n\t    \u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n\u0026lt;/plugins\u0026gt;\n\u0026lt;/build\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.2  负载均衡","pId":"26c49d2","name":"2.2  负载均衡","parent":"八、框架/02 springboot-dubbo","order":1,"sort_id":1340233,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Cp\u003E.keep\u003C/p\u003E"},{"id":"437cabd","pId":"4f9a92e","name":"01 ActiveMQ","parent":"六、中间件","sort_id":1060680,"order":1,"isParent":true,"extname":null,"open":false},{"id":"1.1 ActiveMQ 安装","pId":"437cabd","name":"1.1 ActiveMQ 安装","parent":"六、中间件/01 ActiveMQ","order":1,"sort_id":1060681,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/jaycekon/p/6225058.html\"\u003EJava消息队列--ActiveMq 初体验\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"http://activemq.apache.org/\"\u003EActiveMq 官网\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-下载安装\" class=\"anchor\" href=\"#2-%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. 下载安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EActiveMQ官网下载地址：\u003Ca href=\"http://activemq.apache.org/download.html\"\u003Ehttp://activemq.apache.org/download.html\u003C/a\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1128/141923_d9755b78_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Col class=\"task-list\"\u003E\n\u003Cli\u003Ebin存放的是脚本文件\u003C/li\u003E\n\u003Cli\u003Econf存放的是基本配置文件\u003C/li\u003E\n\u003Cli\u003Edata存放的是日志文件\u003C/li\u003E\n\u003Cli\u003Edocs存放的是说明文档\u003C/li\u003E\n\u003Cli\u003Eexamples存放的是简单的实例\u003C/li\u003E\n\u003Cli\u003Elib存放的是activemq所需jar包\u003C/li\u003E\n\u003Cli\u003Ewebapps用于存放项目的目录\u003C/li\u003E\n\u003C/ol\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-启动activemq\" class=\"anchor\" href=\"#3-%E5%90%AF%E5%8A%A8activemq\"\u003E\u003C/a\u003E3. 启动ActiveMQ　\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost apache-activemq-5.15.8]$ cd bin/\n[fxz@localhost bin]$ ./activemq start\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-访问\" class=\"anchor\" href=\"#4-%E8%AE%BF%E9%97%AE\"\u003E\u003C/a\u003E4. 访问\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EActiveMQ默认启动时，启动了内置的jetty服务器，提供一个用于监控ActiveMQ的admin应用。 \n\nadmin：http://127.0.0.1:8161/admin/\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1128/142322_f1e4a454_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E　　我们在浏览器打开链接之后输入账号密码（这里和tomcat 服务器类似）\u003C/p\u003E\n\u003Cp\u003E　　默认账号：admin\u003C/p\u003E\n\u003Cp\u003E　　密码：admin\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-停止activemq\" class=\"anchor\" href=\"#5-%E5%81%9C%E6%AD%A2activemq\"\u003E\u003C/a\u003E5. 停止ActiveMQ　\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost apache-activemq-5.15.8]$ cd bin/\n[fxz@localhost bin]$ ./activemq stop\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.1 IDEA中进行自定义maven骨架","pId":"5c8b4c4","name":"1.1 IDEA中进行自定义maven骨架","parent":"十、其它","order":1,"sort_id":1214593,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1创建模板maven工程\" class=\"anchor\" href=\"#1%E5%88%9B%E5%BB%BA%E6%A8%A1%E6%9D%BFmaven%E5%B7%A5%E7%A8%8B\"\u003E\u003C/a\u003E1、创建模板maven工程\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/102924_e7ded36f_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E根据实际需求创建\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"11-工程创建好之后--需要在pom文件中添加创建骨架的插件\" class=\"anchor\" href=\"#11-%E5%B7%A5%E7%A8%8B%E5%88%9B%E5%BB%BA%E5%A5%BD%E4%B9%8B%E5%90%8E--%E9%9C%80%E8%A6%81%E5%9C%A8pom%E6%96%87%E4%BB%B6%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%88%9B%E5%BB%BA%E9%AA%A8%E6%9E%B6%E7%9A%84%E6%8F%92%E4%BB%B6\"\u003E\u003C/a\u003E1.1 工程创建好之后 , 需要在pom文件中添加创建骨架的插件.\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;plugin\u0026gt;\n    \u0026lt;groupId\u0026gt;org.apache.maven.plugins\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;maven-archetype-plugin\u0026lt;/artifactId\u0026gt;\n    \u0026lt;version\u0026gt;3.0.0\u0026lt;/version\u0026gt;\n\u0026lt;/plugin\u0026gt; \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-执行命令\" class=\"anchor\" href=\"#2-%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E2. 执行命令\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"21-生成archetype\" class=\"anchor\" href=\"#21-%E7%94%9F%E6%88%90archetype\"\u003E\u003C/a\u003E2.1 生成archetype\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E执行命令: archetype:create-from-project\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/103511_6b84e352_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E执行完毕后，会在target下生成archetype目录\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/103720_cc432cc6_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"22-安装install\" class=\"anchor\" href=\"#22-%E5%AE%89%E8%A3%85install\"\u003E\u003C/a\u003E2.2 安装install\u003C/h4\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/104000_d888bf0e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"23-执行archetypecrawl\" class=\"anchor\" href=\"#23-%E6%89%A7%E8%A1%8Carchetypecrawl\"\u003E\u003C/a\u003E2.3 执行archetype:crawl\u003C/h4\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/111024_737f3fbd_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E执行完毕，会在本地私仓生成archetype-catalog.xml\nE:\\deve\\tools\\apache-maven-3.3.9\\repository\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/111157_d0da6ce9_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-使用自己的骨架\" class=\"anchor\" href=\"#3-%E4%BD%BF%E7%94%A8%E8%87%AA%E5%B7%B1%E7%9A%84%E9%AA%A8%E6%9E%B6\"\u003E\u003C/a\u003E3. 使用自己的骨架\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/111317_4e2e2767_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-删除骨架\" class=\"anchor\" href=\"#4-%E5%88%A0%E9%99%A4%E9%AA%A8%E6%9E%B6\"\u003E\u003C/a\u003E4. 删除骨架\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ewindows下面的：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003EC:\\Users\\wang.IntelliJIdea2018.1\\system\\Maven\\Indices\\UserArchetypes.xml \u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ELinux和mac的可以参见：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/yirentianran/article/details/52232523\"\u003Ehttps://blog.csdn.net/yirentianran/article/details/52232523\u003C/a\u003E\u003C/p\u003E"},{"id":"1.1.2 string 类型命令","pId":"ed9af11","name":"1.1.2 string 类型命令","parent":"四、数据库/01 redis/1.1 Redis 命令","order":1,"sort_id":990608,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Eset key value\u003C/td\u003E\n\u003Ctd\u003E设置指定 key 的值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Eget key\u003C/td\u003E\n\u003Ctd\u003E获取指定 key 的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Egetrange key start end\u003C/td\u003E\n\u003Ctd\u003E返回 key 中字符串值的子字符\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Egetset key value\u003C/td\u003E\n\u003Ctd\u003E将给定 key 的值设为 value ，并返回 key 的旧值(old value)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Egetbit key offset\u003C/td\u003E\n\u003Ctd\u003E对 key 所储存的字符串值，获取指定偏移量上的位(bit)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Emget key1 [key2..]\u003C/td\u003E\n\u003Ctd\u003E获取所有(一个或多个)给定 key 的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Esetbit key offset value\u003C/td\u003E\n\u003Ctd\u003E对 key 所储存的字符串值，设置或清除指定偏移量上的位(bit)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Esetex key seconds value\u003C/td\u003E\n\u003Ctd\u003E将值 value 关联到 key ，并将 key 的过期时间设为 seconds (以秒为单位)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Esetnx key value\u003C/td\u003E\n\u003Ctd\u003E只有在 key 不存在时设置 key 的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Esetrange key offset value\u003C/td\u003E\n\u003Ctd\u003E用 value 参数覆写给定 key 所储存的字符串值，从偏移量 offset 开始。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Estrlen key\u003C/td\u003E\n\u003Ctd\u003E返回 key 所储存的字符串值的长度。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Emset key value [key value ...]\u003C/td\u003E\n\u003Ctd\u003E同时设置一个或多个 key-value 对。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Emsetnx key value [key value ...]\u003C/td\u003E\n\u003Ctd\u003E同时设置一个或多个 key-value 对，当且仅当所有给定 key 都不存在。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Epsetex key milliseconds value\u003C/td\u003E\n\u003Ctd\u003E这个命令和 setex 命令相似，但它以毫秒为单位设置 key 的生存时间，而不是像 setex 命令那样，以秒为单位。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Eincr key\u003C/td\u003E\n\u003Ctd\u003E将 key 中储存的数字值增一。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Eincrby key increment\u003C/td\u003E\n\u003Ctd\u003E将 key 所储存的值加上给定的增量值（increment） 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E17\u003C/td\u003E\n\u003Ctd\u003Eincrbyfloat key increment\u003C/td\u003E\n\u003Ctd\u003E将 key 所储存的值加上给定的浮点增量值（increment） 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E18\u003C/td\u003E\n\u003Ctd\u003Edecr key\u003C/td\u003E\n\u003Ctd\u003E将 key 中储存的数字值减一。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E19\u003C/td\u003E\n\u003Ctd\u003Edecrby key decrement\u003C/td\u003E\n\u003Ctd\u003Ekey 所储存的值减去给定的减量值（decrement） 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E20\u003C/td\u003E\n\u003Ctd\u003Eappend key value\u003C/td\u003E\n\u003Ctd\u003E如果 key 已经存在并且是一个字符串， append 命令将指定的 value 追加到该 key 原来值（value）的末尾。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"e3fc66b","pId":"d1f6d69","name":"1.2 redis 高级","parent":"四、数据库/01 redis","sort_id":1017121,"order":1,"isParent":true,"extname":null,"open":false},{"id":"1.2.1 主从","pId":"e3fc66b","name":"1.2.1 主从","parent":"四、数据库/01 redis/1.2 redis 高级","order":1,"sort_id":1024028,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-准备三个redis服务masterslave1slave2\" class=\"anchor\" href=\"#1-%E5%87%86%E5%A4%87%E4%B8%89%E4%B8%AAredis%E6%9C%8D%E5%8A%A1masterslave1slave2\"\u003E\u003C/a\u003E1. 准备三个redis服务，master,slave1,slave2.\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1修改redisconf-配置\" class=\"anchor\" href=\"#1%E4%BF%AE%E6%94%B9redisconf-%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E（1）修改redis.conf 配置\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Emaster配置：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 设置端口\nport 6000\n\n# 设置密码\nrequirepass 123456\n\n# 修改主机ip\nbind 192.168.222.132 127.0.0.1\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eslave1、slave2修改配置：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eport 6001\nrequirepass 123456\n \n# 配置master的ip port\nslaveof 127.0.0.1 6000\n# 配置master的密码\nmasterauth 123456\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2启动服务\" class=\"anchor\" href=\"#2%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1\"\u003E\u003C/a\u003E（2）启动服务\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动master\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# cd /usr/local/redis-4.0.11/src\n[root@localhost src]# ./redis-server ../redis.conf\n[root@localhost src]# ./redis-cli \n127.0.0.1:6379\u0026gt; info\n\n\n# Replication  由于从服务器还没启动，所以看到的slave数量为0\nrole:master\nconnected_slaves:0\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动slave1、slave2\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# cd /usr/local/redis-4.0.11/src\n[root@localhost src]# ./redis-server ../redis.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E验证\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# ./redis-cli\n[root@localhost src]# info\n\n# Replication \nrole:master\nconnected_slaves:2\nslave0:ip=192.168.222.133,port=6379,state=online,offset=1832,lag=1\nslave1:ip=192.168.222.134,port=6379,state=online,offset=1832,lag=0\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E可以在master上set key，然后在slave上get key，测试能否同步取到\u003C/p\u003E"},{"id":"1.2.3.3 集群常用命令","pId":"c07e325","name":"1.2.3.3 集群常用命令","parent":"四、数据库/01 redis/1.2 redis 高级/1.2.3 集群","order":1,"sort_id":1047683,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-命令\" class=\"anchor\" href=\"#1-%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster info\u003C/td\u003E\n\u003Ctd\u003E打印集群的信息\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster nodes\u003C/td\u003E\n\u003Ctd\u003E列出集群当前已知的所有节点信息\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster meet  \u003C/td\u003E\n\u003Ctd\u003E将 ip 和 port 所指定的节点添加到集群当中，让它成为集群的一份子。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster forget \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E从集群中移除 node_id 指定的节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster replicate \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E将当前节点设置为 node_id 指定的节点的从节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster saveconfig\u003C/td\u003E\n\u003Ctd\u003E将节点的配置文件保存到硬盘里面。槽(slot)\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster addslots  [slot ...]\u003C/td\u003E\n\u003Ctd\u003E将一个或多个槽（ slot）指派（ assign）给当前节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster delslots  [slot ...]\u003C/td\u003E\n\u003Ctd\u003E移除一个或多个槽对当前节点的指派。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster flushslots\u003C/td\u003E\n\u003Ctd\u003E移除指派给当前节点的所有槽，让当前节点变成一个没有指派任何槽的节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  node \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E将槽 slot 指派给 node_id 指定的节点，如果槽已经指派给另一个节点，那么先让另一个节点删除该槽\u0026gt;，然后再进行指派。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  migrating \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E将本节点的槽 slot 迁移到 node_id 指定的节点中。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  importing \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E从 node_id 指定的节点中导入槽 slot 到本节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  stable\u003C/td\u003E\n\u003Ctd\u003E取消对槽 slot 的导入（ import）或者迁移（ migrate）。键\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster keyslot \u003C/td\u003E\n\u003Ctd\u003E计算键 key 应该被放置在哪个槽上。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster countkeysinslot \u003C/td\u003E\n\u003Ctd\u003E返回槽 slot 目前包含的键值对数量。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster getkeysinslot  \u003C/td\u003E\n\u003Ctd\u003E返回 count 个 slot 槽中的键\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"2.1 Oracle 12c创建PDB用户并设置默认表空间","pId":"cd26332","name":"2.1 Oracle 12c创建PDB用户并设置默认表空间","parent":"四、数据库/02 oracle","order":1,"sort_id":1129838,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/fanyongbin/p/5699482.html\"\u003EOracle 12c创建PDB用户并设置默认表空间\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-创建pdb数据库\" class=\"anchor\" href=\"#2-%E5%88%9B%E5%BB%BApdb%E6%95%B0%E6%8D%AE%E5%BA%93\"\u003E\u003C/a\u003E2. 创建PDB数据库\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E选择Database Configuration Assistant\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1213/152034_56ab7765_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E设置全局数据库名及PDB名\n\u003Cimg src=\"https://static.oschina.net/uploads/img/201812/13094942_9g8X.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E- CDB名：xlauch\n- PDB名：xlauch_db\n- 管理口令：Xlauch123456\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201812/13095810_FpkD.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201812/13101927_mCyn.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-创建表空间\" class=\"anchor\" href=\"#3-%E5%88%9B%E5%BB%BA%E8%A1%A8%E7%A9%BA%E9%97%B4\"\u003E\u003C/a\u003E3. 创建表空间\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 创建临时表空间\ncreate temporary tablespace i84_temp\ntempfile 'E:\\deve\\db\\oracle\\tablespace\\i84_temp.dbf'\nsize 32m\nautoextend on\nnext 32m MAXSIZE unlimited  \nextent management local;\n\n# 创建数据表空间\ncreate tablespace i84_data\nlogging\ndatafile 'E:\\deve\\db\\oracle\\tablespace\\i84_data.dbf'\nsize 100m\nautoextend on\nnext 50m MAXSIZE unlimited  \nextent management local;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-创建用户\" class=\"anchor\" href=\"#4-%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7\"\u003E\u003C/a\u003E4. 创建用户\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecreate user xlauch identified by xlauch \ndefault tablespace i84_data  \ntemporary tablespace i84_temp;\n\n# 用户授权\ngrant create session,resource,dba to xlauch;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-配置tnsname\" class=\"anchor\" href=\"#5-%E9%85%8D%E7%BD%AEtnsname\"\u003E\u003C/a\u003E5. 配置tnsname\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Ei84 =\n  (DESCRIPTION =\n    (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))\n    (CONNECT_DATA =\n      (SERVER = DEDICATED)\n      (SERVICE_NAME = xlauch_db)\n    )\n  )\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-使用plsql-连接\" class=\"anchor\" href=\"#6-%E4%BD%BF%E7%94%A8plsql-%E8%BF%9E%E6%8E%A5\"\u003E\u003C/a\u003E6. 使用pl/SQL 连接\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1213/152540_83e584cc_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"1.3 同步和异步","pId":"2fc41b2","name":"1.3 同步和异步","parent":"一、并发编程/01  线程基础","order":2,"sort_id":679412,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 对象锁的同步和异步问题\n * @author alienware\n *\n */\npublic class MyObject {\n\n\tpublic synchronized void method1(){\n\t\ttry {\n\t\t\tSystem.out.println(Thread.currentThread().getName());\n\t\t\tThread.sleep(4000);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t/** synchronized */\n\tpublic void method2(){\n\t\t\tSystem.out.println(Thread.currentThread().getName());\n\t}\n\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal MyObject mo = new MyObject();\n\t\t\n\t\t/**\n\t\t * 分析：\n\t\t * t1线程先持有object对象的Lock锁，t2线程可以以异步的方式调用对象中的非synchronized修饰的方法\n\t\t * t1线程先持有object对象的Lock锁，t2线程如果在这个时候调用对象中的同步（synchronized）方法则需等待，也就是同步\n\t\t */\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmo.method1();\n\t\t\t}\n\t\t},\"t1\");\n\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmo.method2();\n\t\t\t}\n\t\t},\"t2\");\n\n\t\tt1.start();\n\t\tt2.start();\n\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"method2\"方法不加synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/114534_c60b6ece_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"method2\"方法加上synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/114707_838e195a_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-案例说明\" class=\"anchor\" href=\"#2-%E6%A1%88%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 案例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，t2线程可以以异步的方式调用对象中的非synchronized修饰的方法\u003C/li\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，t2线程如果在这个时候调用对象中的同步（synchronized）方法则需等待，也就是同步\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.3 线程变量","pId":"77fbb9c","name":"2.3 线程变量","parent":"一、并发编程/02 多线程通信","order":2,"sort_id":688447,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8B\"\u003E\u003C/a\u003E1 示例\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ConnThreadLocal {\n\n\tpublic static ThreadLocal\u0026lt;String\u0026gt; th = new ThreadLocal\u0026lt;String\u0026gt;();\n\t\n\tpublic void setTh(String value){\n\t\tth.set(value);\n\t}\n\tpublic void getTh(){\n\t\tSystem.out.println(Thread.currentThread().getName() + \":\" + this.th.get());\n\t}\n\t\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\t\n\t\tfinal ConnThreadLocal ct = new ConnThreadLocal();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tct.setTh(\"张三\");\n\t\t\t\tct.getTh();\n\t\t\t}\n\t\t}, \"t1\");\n\t\t\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\ttry {\n\t\t\t\t\tThread.sleep(1000);\n\t\t\t\t\tct.getTh();\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}, \"t2\");\n\t\t\n\t\tt1.start();\n\t\tt2.start();\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.4.3 Queeue几个实现","pId":"75d372a","name":"2.4.3 Queeue几个实现","parent":"一、并发编程/02 多线程通信/2.4 高并发容器","order":2,"sort_id":698153,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-concurrentlinkedqueue-高性能无阻塞无界队列\" class=\"anchor\" href=\"#1-concurrentlinkedqueue-%E9%AB%98%E6%80%A7%E8%83%BD%E6%97%A0%E9%98%BB%E5%A1%9E%E6%97%A0%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E1. ConcurrentLinkedQueue 高性能无阻塞无界队列\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E//高性能无阻塞无界队列：ConcurrentLinkedQueue\nConcurrentLinkedQueue\u0026lt;String\u0026gt; q = new ConcurrentLinkedQueue\u0026lt;String\u0026gt;();\nq.offer(\"a\");\nq.offer(\"b\");\nq.offer(\"c\");\nq.offer(\"d\");\nq.add(\"e\");\n\nSystem.out.println(q.poll());\t//a 从头部取出元素，并从队列里删除\nSystem.out.println(q.size());\t//4\nSystem.out.println(q.peek());\t//b\nSystem.out.println(q.size());\t//4\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E因为在Queeue中定义了\"add\"与\"offer\"方法，在ConcurrentListQueeue中两个方法一致无区别\u003C/li\u003E\n\u003Cli\u003E\"poll\"方法：获取首个元素并删除\u003C/li\u003E\n\u003Cli\u003E\"add\"方法：获取首个元素不删除\u003C/li\u003E\n\u003Cli\u003E\"FIFO\" 规则\u003C/li\u003E\n\u003Cli\u003E元素不允许为null\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-arrayblockingqueue-数组阻塞有界队列\" class=\"anchor\" href=\"#2-arrayblockingqueue-%E6%95%B0%E7%BB%84%E9%98%BB%E5%A1%9E%E6%9C%89%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E2. ArrayBlockingQueue 数组阻塞有界队列\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EArrayBlockingQueue\u0026lt;String\u0026gt; array = new ArrayBlockingQueue\u0026lt;String\u0026gt;(5);\narray.put(\"a\");\narray.put(\"b\");\narray.add(\"c\");\narray.add(\"d\");\narray.add(\"e\");\narray.add(\"f\");\n//System.out.println(array.offer(\"a\", 3, TimeUnit.SECONDS));\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E声明时候需指定容量\u003C/li\u003E\n\u003Cli\u003E\"offer\"方法：可以延迟添加，返回是否添加成功\u003C/li\u003E\n\u003Cli\u003E没有实现读写分离，无法进行并行操作\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-linkedblockingqueue-链式阻塞队列\" class=\"anchor\" href=\"#3-linkedblockingqueue-%E9%93%BE%E5%BC%8F%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E3. LinkedBlockingQueue 链式阻塞队列\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003ELinkedBlockingQueue\u0026lt;String\u0026gt; q = new LinkedBlockingQueue\u0026lt;String\u0026gt;();\nq.offer(\"a\");\nq.offer(\"b\");\nq.offer(\"c\");\nq.offer(\"d\");\nq.offer(\"e\");\nq.add(\"f\");\n\nSystem.out.println(q);\n\nList\u0026lt;String\u0026gt; list = new ArrayList\u0026lt;String\u0026gt;();\nSystem.out.println(q.drainTo(list, 3));\nSystem.out.println(list.size());\nfor (String string : list) {\n System.out.println(string);\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以指定容量：new LinkedBlockingQueue(5);\u003C/li\u003E\n\u003Cli\u003E内部实现分离锁（读写两把锁），可以实现生产与消费并行\u003C/li\u003E\n\u003Cli\u003E无界队列，内部有链式缓冲区\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4synchronousqueue-同步\" class=\"anchor\" href=\"#4synchronousqueue-%E5%90%8C%E6%AD%A5\"\u003E\u003C/a\u003E4.SynchronousQueue 同步\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Efinal SynchronousQueue\u0026lt;String\u0026gt; q = new SynchronousQueue\u0026lt;String\u0026gt;();\nThread t1 = new Thread(new Runnable() {\n    @Override\n    public void run() {\n        try {\n            System.out.println(q.take());\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n});\nt1.start();\nThread t2 = new Thread(new Runnable() {\n    \n    @Override\n    public void run() {\n        q.add(\"asdasd\");\n    }\n});\nt2.start();\t\t\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E需先执行take操作，才能执行add操作\u003C/li\u003E\n\u003Cli\u003E本身队列不存放元素，只是把数据转发\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5priorityblockingqueue-优先级队列\" class=\"anchor\" href=\"#5priorityblockingqueue-%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E5.PriorityBlockingQueue 优先级队列\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Etask 类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Task implements Comparable\u0026lt;Task\u0026gt;{\n\t\n\tprivate int id ;\n\tprivate String name;\n\tpublic int getId() {\n\t\treturn id;\n\t}\n\tpublic void setId(int id) {\n\t\tthis.id = id;\n\t}\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\t\n\t@Override\n\tpublic int compareTo(Task task) {\n\t\treturn this.id \u0026gt; task.id ? 1 : (this.id \u0026lt; task.id ? -1 : 0);  \n\t}\n\t\n\tpublic String toString(){\n\t\treturn this.id + \",\" + this.name;\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class UsePriorityBlockingQueue {\n\n\t\n\tpublic static void main(String[] args) throws Exception{\n\t\t\n\t\t\n\t\tPriorityBlockingQueue\u0026lt;Task\u0026gt; q = new PriorityBlockingQueue\u0026lt;Task\u0026gt;();\n\t\t\n\t\tTask t1 = new Task();\n\t\tt1.setId(3);\n\t\tt1.setName(\"id为3\");\n\t\tTask t2 = new Task();\n\t\tt2.setId(4);\n\t\tt2.setName(\"id为4\");\n\t\tTask t3 = new Task();\n\t\tt3.setId(1);\n\t\tt3.setName(\"id为1\");\n\t\t\n\t\t//return this.id \u0026gt; task.id ? 1 : 0;\n\t\tq.add(t1);\t//3\n\t\tq.add(t2);\t//4\n\t\tq.add(t3);  //1\n\t\t\n\t\t// 1 3 4\n\t\tSystem.out.println(\"容器：\" + q);\n\t\tSystem.out.println(q.take().getId());\n\t\tSystem.out.println(\"容器：\" + q);\n//\t\tSystem.out.println(q.take().getId());\n//\t\tSystem.out.println(q.take().getId());\n\t\t\n\n\t\t\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E元素必须实现\"Comparable\"接口\u003C/li\u003E\n\u003Cli\u003E添加元素不排序，take时进行排序\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6delayqueue-延迟带时间队列\" class=\"anchor\" href=\"#6delayqueue-%E5%BB%B6%E8%BF%9F%E5%B8%A6%E6%97%B6%E9%97%B4%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E6.DelayQueue 延迟带时间队列\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EWangmin 类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Wangmin implements Delayed {\n\n    private String name;\n    //身份证  \n    private String id;\n    //截止时间  \n    private long endTime;\n    //定义时间工具类\n    private TimeUnit timeUnit = TimeUnit.SECONDS;\n\n    public Wangmin(String name, String id, long endTime) {\n        this.name = name;\n        this.id = id;\n        this.endTime = endTime;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getId() {\n        return this.id;\n    }\n\n    /**\n     * 用来判断是否到了截止时间\n     */\n    @Override\n    public long getDelay(TimeUnit unit) {\n        //return unit.convert(endTime, TimeUnit.MILLISECONDS) - unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);\n        return endTime - System.currentTimeMillis();\n    }\n\n    /**\n     * 相互批较排序用\n     */\n    @Override\n    public int compareTo(Delayed delayed) {\n        Wangmin w = (Wangmin) delayed;\n        return this.getDelay(this.timeUnit) - w.getDelay(this.timeUnit) \u0026gt; 0 ? 1 : 0;\n    }\n\n\n}  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003E\npublic class WangBa implements Runnable {  \n    \n    private DelayQueue\u0026lt;Wangmin\u0026gt; queue = new DelayQueue\u0026lt;Wangmin\u0026gt;();  \n    \n    public boolean yinye =true;  \n      \n    public void shangji(String name,String id,int money){  \n        Wangmin man = new Wangmin(name, id, 1000 * money + System.currentTimeMillis());  \n        System.out.println(\"网名\"+man.getName()+\" 身份证\"+man.getId()+\"交钱\"+money+\"块,开始上机...\");  \n        this.queue.add(man);  \n    }  \n      \n    public void xiaji(Wangmin man){  \n        System.out.println(\"网名\"+man.getName()+\" 身份证\"+man.getId()+\"时间到下机...\");  \n    }  \n  \n    @Override  \n    public void run() {  \n        while(yinye){  \n            try {  \n                Wangmin man = queue.take();  \n                xiaji(man);  \n            } catch (InterruptedException e) {  \n                e.printStackTrace();  \n            }  \n        }  \n    }  \n      \n    public static void main(String args[]){  \n        try{  \n            System.out.println(\"网吧开始营业\");  \n            WangBa siyu = new WangBa();  \n            Thread shangwang = new Thread(siyu);  \n            shangwang.start();  \n              \n            siyu.shangji(\"路人甲\", \"123\", 1);  \n            siyu.shangji(\"路人乙\", \"234\", 10);  \n            siyu.shangji(\"路人丙\", \"345\", 5);  \n        }  \n        catch(Exception e){  \n            e.printStackTrace();\n        }  \n  \n    }  \n}  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E元素需实现\"Delayed\"接口\u003C/li\u003E\n\u003Cli\u003E无界队列，有读写锁\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0828/094434_9dbced71_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"2.6.3 Future和Callable","pId":"3b56f09","name":"2.6.3 Future和Callable","parent":"一、并发编程/02 多线程通信/2.6 concurrent工具类","order":2,"sort_id":748709,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/11\n */\npublic class TestFuture implements Callable\u0026lt;String\u0026gt; {\n\n    private static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    private String param;\n\n    public TestFuture(String param) {\n        this.param = param;\n    }\n\n    @Override\n    public String call() throws Exception {\n        Thread.sleep(2000);\n        return format.format(new Date()) + \"  \" + param + \" 执行结束\";\n    }\n\n\n    /**\n     * @param args\n     */\n    public static void main(String[] args) throws Exception {\n        ExecutorService executorService = Executors.newFixedThreadPool(2);\n\n        System.out.println(format.format(new Date()) + \" 开始执行\");\n\n        FutureTask\u0026lt;String\u0026gt; futureTask1 = new FutureTask\u0026lt;String\u0026gt;(new TestFuture(\"张三\"));\n        FutureTask\u0026lt;String\u0026gt; futureTask2 = new FutureTask\u0026lt;String\u0026gt;(new TestFuture(\"李四\"));\n\n        // 当future.get() == null 时表示执行完成\n        Future f1 = executorService.submit(futureTask1);\n        // 如果此处调用future.get()，那么主线程将阻塞直到执行完毕\n//        System.out.println(f1.get());\n        Future f2 = executorService.submit(futureTask2);\n\n        // 执行点其它事情\n        System.out.println(\"执行点其它事情\");\n        Thread.sleep(1500);\n\n        // 获取执行结果\n        System.out.println(futureTask1.get());\n        System.out.println(futureTask2.get());\n\n        System.out.println(format.format(new Date()) + \" 执行结束\");\n        executorService.shutdown();\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0911/170129_2e945d2e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以实现线程并行\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.8.2 Disruptor 对象创建说明","pId":"6619c4c","name":"2.8.2 Disruptor 对象创建说明","parent":"一、并发编程/02 多线程通信/2.8 disruptor","order":2,"sort_id":821414,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1disruptor示例demo\" class=\"anchor\" href=\"#1disruptor%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1.Disruptor示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建disruptor\n * @param eventFactory      ： 创建事件工厂\n * @param ringBufferSize    ： ringbuffer大小 ，必须是2的N次方\n * @param executor          :  线程池\n * @param producerType      :  生产者类型\n *                                  ProducerType.SINGLE：单个生产者\n *                                  ProducerType.MULTI: 多个生产者\n * @param waitStrategy      :  等待策略\n *                                  BlockingWaitStrategy 是最低效的策略，但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现\n *                                  SleepingWaitStrategy 的性能表现跟BlockingWaitStrategy差不多，对CPU的消耗也类似，但其对生产者线程的影响最小，适合用于异步日志类似的场景\n *                                  YieldingWaitStrategy 的性能是最好的，适合用于低延迟的系统。在要求极高性能且事件处理线数小于CPU逻辑核心数的场景中，推荐使用此策略；例如，CPU开启超线程的特性\n */\nDisruptor\u0026lt;UserEvent\u0026gt; disruptor = new Disruptor\u0026lt;UserEvent\u0026gt;(eventFactory, ringBufferSize, executor, ProducerType.SINGLE, new YieldingWaitStrategy());\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EEvent            : 事件对象，可以理解生产者和消费者交互过程中，传输的对象，一般POJO\u003C/li\u003E\n\u003Cli\u003EEventFactory     : 事件工厂，在disruptor初始化时，需要在往ringbuffer中创建初始化事件对象\u003C/li\u003E\n\u003Cli\u003EEventProducer    : 事件生产者，用于发布事件，先从ringbuffer中获取为被使用的初始对象，进行加工，然后发布出去\u003C/li\u003E\n\u003Cli\u003ERingBuffer       : 事件缓存地方：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-通俗理解不一定贴切\" class=\"anchor\" href=\"#2-%E9%80%9A%E4%BF%97%E7%90%86%E8%A7%A3%E4%B8%8D%E4%B8%80%E5%AE%9A%E8%B4%B4%E5%88%87\"\u003E\u003C/a\u003E2. 通俗理解（不一定贴切）\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EEvent            : 牛奶盒\u003C/li\u003E\n\u003Cli\u003EEventFactory     : 生产空的牛奶盒、放到生产线\u003C/li\u003E\n\u003Cli\u003ERingBuffer       : 生产线，上面流转着等待灌装的空的牛奶盒\u003C/li\u003E\n\u003Cli\u003EEventProducer    : 从生产线拿走一个空的牛奶盒，注入牛奶，卖个客人\u003C/li\u003E\n\u003Cli\u003EDisruptor        : 生产车间\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2116d9f","pId":0,"name":"三、linux ","parent":"","sort_id":871095,"order":2,"isParent":true,"extname":null,"open":false},{"id":"2.3 xmanager 连接centos7","pId":"6275c3c","name":"2.3 xmanager 连接centos7","parent":"三、linux /02 系统操作","order":2,"sort_id":987034,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"http://blog.netsarang.com/89/connecting-to-centos-7/\"\u003Exmanager 连接centos7\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-安装\" class=\"anchor\" href=\"#2-%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. 安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装epel源\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install epel-release\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E切换到root用户\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esu root\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装lightdm\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install lightdm\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改配置文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecp lightdm.conf  lightdm.conf.bak\nvim /etc/lightdm/lightdm.conf\n\n# 配置内容：\n[XDMCPServer]\nenabled=false\nport=177\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改CentOS7默认的显示管理器为lightdm，命令为：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esystemctl disable gdm \n\nsystemctl enable lightdm\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动lightdm，命令为：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esystemctl stop gdm\nsystemctl start lightdm\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关闭防火墙\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esystemctl stop firewalld.service\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E以yum方式继续安装xfce轻量级桌面环境，命令为：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum groupinstall xfce\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在Windows上打开Xstart，输入各项配置信息和命令（/usr/bin/xfce4-session），点击运行即可远程连接CentOS7，如图：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1031/100006_b2b71368_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"3.2.2 权限管理","pId":"ebcfc3b","name":"3.2.2 权限管理","parent":"三、linux /03 常用命令/3.2 权限命令","order":2,"sort_id":987049,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Col class=\"task-list\"\u003E\n\u003Cli\u003E查看文件权限设置\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E//查看/bin/bash文件的权限\nls -al /bin/bash\n//结果如下\n-rwxr-xr-x 1 root root 938736 Apr 23  2012 /bin/bash\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E第1位给出了该项的属性，即是文件还是目录，或者是链接文件等。\u003C/li\u003E\n\u003Cli\u003E-：表示是文件，如上面的案例就是一个文件；\u003C/li\u003E\n\u003Cli\u003Ed：表示是目录；\u003C/li\u003E\n\u003Cli\u003El：表示是链接文件。\u003C/li\u003E\n\u003Cli\u003E第2、3、4位给出了文件或目录所有者的权限。\u003C/li\u003E\n\u003Cli\u003E第5、6、7位给出了文件或目录所属用户组的权限。\u003C/li\u003E\n\u003Cli\u003E第8、9、10位给出了其他用户权限。\u003C/li\u003E\n\u003Cli\u003Er：为读权限。\u003C/li\u003E\n\u003Cli\u003Ew：为写权限。\u003C/li\u003E\n\u003Cli\u003Ex：为执行权限。目录的执行权限的意思是可以用cd命令进入该目录\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E2、chmod命令：该命令用来修改文件或目录的访问权限。\u003C/p\u003E\n\u003Cp\u003E第一种方式为：chmod a+r 文件或目录名\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E其中a可用u、g、o替换，+可用=、-替换，r可用w、x替换\u003C/li\u003E\n\u003Cli\u003Ea：表示修改所有用户的权限。包括u、g、o\u003C/li\u003E\n\u003Cli\u003Eu：表示只给文件或目录所有者修改权限\u003C/li\u003E\n\u003Cli\u003Eg：表示给文件所有组修改权限\u003C/li\u003E\n\u003Cli\u003Eo：表示给其他用户修改权限\u003C/li\u003E\n\u003Cli\u003E+：表示增加某种权限\u003C/li\u003E\n\u003Cli\u003E-：表示减去某种权限\u003C/li\u003E\n\u003Cli\u003E=：表示赋予某种权限\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E第二种方式为：用数字表示权限，r：用4表示 w：用2表示 x：用1表示\n则1~7表示的权限如下：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1：–x\u003C/li\u003E\n\u003Cli\u003E2:：-w-\u003C/li\u003E\n\u003Cli\u003E3：-wx\u003C/li\u003E\n\u003Cli\u003E4：r–\u003C/li\u003E\n\u003Cli\u003E5：r-x\u003C/li\u003E\n\u003Cli\u003E6：rw-\u003C/li\u003E\n\u003Cli\u003E7：rwx\u003C/li\u003E\n\u003Cli\u003E于是可用“chmod 777 文件或目录名”命令来修改权限。三个7中第一个代表所有者权限，第二个代表所有组权限，第三个代表其他用户权限。当然，也可用类似于“chmod u+2文件目录名”的方式来修改权限。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E附：\n实例一：将/usr/local/test目录及其子目录的读、写、执行权限开放给所有用户\u003C/p\u003E\n\u003Cp\u003E-R表示修改当前目录及其子目录，不加-R仅修改当前目录\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Echmod -R 777 /usr/local/test \n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2. Thumbnails 生成缩略图","pId":"97a5782","name":"2. Thumbnails 生成缩略图","parent":"九、工具类","order":2,"sort_id":1184536,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-引入pomxml\" class=\"anchor\" href=\"#1-%E5%BC%95%E5%85%A5pomxml\"\u003E\u003C/a\u003E1. 引入pom.xml\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;dependency\u0026gt;\n    \u0026lt;groupId\u0026gt;net.coobird\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;thumbnailator\u0026lt;/artifactId\u0026gt;\n    \u0026lt;version\u0026gt;0.4.8\u0026lt;/version\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-测试demo\" class=\"anchor\" href=\"#2-%E6%B5%8B%E8%AF%95demo\"\u003E\u003C/a\u003E2. 测试demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.ext.face.excel;\n\n\nimport net.coobird.thumbnailator.Thumbnails;\n\nimport java.io.File;\nimport java.io.IOException;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/12/22\n */\npublic class ResizeImage2 {\n\n    /**\n     * @param standardImgPath 原图片path\n     * @param thumName        缩略图path\n     */\n    private static String storeThumbnail(String standardImgPath, String thumName) {\n        File file = new File(standardImgPath);\n        if (file != null \u0026amp;\u0026amp; file.isFile()) {\n            try {\n                File outFIle = new File(thumName);\n                Thumbnails.of(file).scale(0.2f).toFile(outFIle);\n                return outFIle.getName();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n        return null;\n    }\n\n\n    public static void main(String[] args) {\n        storeThumbnail(\"C:\\\\Users\\\\dell\\\\Desktop\\\\error\\\\24270.jpg\", \"C:\\\\Users\\\\dell\\\\Desktop\\\\error\\\\24270_0.jpg\");\n    }\n\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"5.1.3 堆参数配置","pId":"008a6af","name":"5.1.3 堆参数配置","parent":"五、java 虚拟机/01 JVM 结构","order":2,"sort_id":1003739,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参数说明\" class=\"anchor\" href=\"#1-%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 参数说明\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E说明\u003C/th\u003E\n\u003Cth\u003E默认配置\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xms\u003C/td\u003E\n\u003Ctd\u003E初始堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmx\u003C/td\u003E\n\u003Ctd\u003E最大堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmn\u003C/td\u003E\n\u003Ctd\u003E配置新生代大小，对系统性能及GC有比较大影响，一般配置在堆大小的1/4到1/3左右\u003C/td\u003E\n\u003Ctd\u003E1/3\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:NewRatio\u003C/td\u003E\n\u003Ctd\u003E老年代/新生代\u003C/td\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:SurvivorRatio\u003C/td\u003E\n\u003Ctd\u003EEden区/Form区的比例=EDEN/FROM=EDEN/TO\u003C/td\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintCommandLineFlags\u003C/td\u003E\n\u003Ctd\u003E输出参数信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGC\u003C/td\u003E\n\u003Ctd\u003E打印GC日志\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGCDetails\u003C/td\u003E\n\u003Ctd\u003E打印GC日志详细信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E提示：可以把初始化堆的大小设置成最大堆的大小，这样可以减少程序运行时垃圾回收的次数，从而提高性能\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例一\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E4%B8%80\"\u003E\u003C/a\u003E2. 示例一\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.jvm;\n\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * -Xms5m -Xmx20m -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+PrintGCDetails\n *\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/11/16\n */\npublic class Test1 {\n\n    /**\n     * 1M 大小\n     */\n    private static final int M_SIZE = 1 * 1024 * 1024;\n\n\n    public static void main(String[] args) {\n        printRunTimeMsg();\n        // 分配1m内存\n        byte[] bytes = new byte[M_SIZE];\n        printRunTimeMsg();\n\n        // 分配3m内存\n        byte[] bytes2 = new byte[3 * M_SIZE];\n        printRunTimeMsg();\n    }\n\n\n    /**\n     * 打印jvm内存信息\n     */\n    private static void printRunTimeMsg() {\n        System.out.println(\"\\n===========================================================\");\n        System.out.println(\"最大内存：\" + getSize(Runtime.getRuntime().maxMemory()));\n        System.out.println(\"初始内存：\" + getSize(Runtime.getRuntime().totalMemory()));\n        System.out.println(\"空闲内存：\" + getSize(Runtime.getRuntime().freeMemory()));\n    }\n\n    /**\n     * 转为M单位\n     *\n     * @param size\n     * @return\n     */\n    private static long getSize(long size) {\n        return size / M_SIZE;\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1116/140412_5f82c927_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"5.2.2 回收器","pId":"8cf0d42","name":"5.2.2 回收器","parent":"五、java 虚拟机/02 垃圾回收","order":2,"sort_id":1015490,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch4\u003E\n\u003Ca id=\"1-串行回收器\" class=\"anchor\" href=\"#1-%E4%B8%B2%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8\"\u003E\u003C/a\u003E1. 串行回收器\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-XX:+UseSerialGC\u003C/li\u003E\n\u003Cli\u003E新生代、老年代都可以使用\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-并行回收器\" class=\"anchor\" href=\"#2-%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8\"\u003E\u003C/a\u003E2. 并行回收器\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-XX:+UseParNewGC\u003C/li\u003E\n\u003Cli\u003E串行回收器的多线程化\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-cms回收器标记清除\" class=\"anchor\" href=\"#3-cms%E5%9B%9E%E6%94%B6%E5%99%A8%E6%A0%87%E8%AE%B0%E6%B8%85%E9%99%A4\"\u003E\u003C/a\u003E3. CMS回收器(标记清除）\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-XX:+UseConcMaskSweepGC\u003C/li\u003E\n\u003Cli\u003E-XX:ConcGCThreads： 线程数量\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4-g1回收器分区算法\" class=\"anchor\" href=\"#4-g1%E5%9B%9E%E6%94%B6%E5%99%A8%E5%88%86%E5%8C%BA%E7%AE%97%E6%B3%95\"\u003E\u003C/a\u003E4. G1回收器（分区算法）\u003C/h4\u003E"},{"id":"2.3 管理控制台安装","pId":"26c49d2","name":"2.3 管理控制台安装","parent":"八、框架/02 springboot-dubbo","order":2,"sort_id":1340234,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch4\u003E\n\u003Ca id=\"1-克隆代码\" class=\"anchor\" href=\"#1-%E5%85%8B%E9%9A%86%E4%BB%A3%E7%A0%81\"\u003E\u003C/a\u003E1. 克隆代码\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit clone https://github.com/dubbo/dubbo-ops.git\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-修改applicationproperties配置信息\" class=\"anchor\" href=\"#2-%E4%BF%AE%E6%94%B9applicationproperties%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E2. 修改\"application.properties\"配置信息\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eserver.port=7001\nspring.velocity.cache=false\nspring.velocity.charset=UTF-8\nspring.velocity.layout-url=/templates/default.vm\nspring.messages.fallback-to-system-locale=false\nspring.messages.basename=i18n/message\nspring.root.password=root\nspring.guest.password=guest\n\ndubbo.registry.address=zookeeper://127.0.0.1:2181\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E注意：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eserver.port：访问端口\u003C/li\u003E\n\u003Cli\u003Espring.root.password ： root 用户密码\u003C/li\u003E\n\u003Cli\u003Espring.guest.password ：guest 用户密码\u003C/li\u003E\n\u003Cli\u003Edubbo.registry.address：zookeeper 注册地址\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-编译打包\" class=\"anchor\" href=\"#3-%E7%BC%96%E8%AF%91%E6%89%93%E5%8C%85\"\u003E\u003C/a\u003E3. 编译打包\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Emvn clean package\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4-启动控制台\" class=\"anchor\" href=\"#4-%E5%90%AF%E5%8A%A8%E6%8E%A7%E5%88%B6%E5%8F%B0\"\u003E\u003C/a\u003E4. 启动控制台\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003EE:\\deve\\workspace\\dubbo\\code\\dubbo-ops\\dubbo-admin\\target\u0026gt; java -jar .\\dubbo-admin-0.0.1-SNAPSHOT.jar\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"5-访问-httplocalhost7001\" class=\"anchor\" href=\"#5-%E8%AE%BF%E9%97%AE-httplocalhost7001\"\u003E\u003C/a\u003E5. 访问 \u003Ca href=\"http://localhost:7001/\"\u003Ehttp://localhost:7001/\u003C/a\u003E\n\u003C/h4\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2019/0227/152339_f06b97ff_907621.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E"},{"id":"f83230e","pId":"c21f20d","name":"03 springcloud","parent":"八、框架","sort_id":1203890,"order":2,"isParent":true,"extname":null,"open":false},{"id":"1.1.3 hash 类型命令","pId":"ed9af11","name":"1.1.3 hash 类型命令","parent":"四、数据库/01 redis/1.1 Redis 命令","order":2,"sort_id":995328,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"redis-哈希hash\" class=\"anchor\" href=\"#redis-%E5%93%88%E5%B8%8Chash\"\u003E\u003C/a\u003Eredis 哈希(hash)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis hash 是一个string类型的field和value的映射表，hash特别适合用于存储对象。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 中每个 hash 可以存储 2^32 - 1 键值对（40多亿）。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Ehdel key field1 [field2]\u003C/td\u003E\n\u003Ctd\u003E删除一个或多个哈希表字段\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ehexists key field\u003C/td\u003E\n\u003Ctd\u003E查看哈希表 key 中，指定的字段是否存在。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Ehget key field\u003C/td\u003E\n\u003Ctd\u003E获取存储在哈希表中指定字段的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Ehgetall key\u003C/td\u003E\n\u003Ctd\u003E获取在哈希表中指定 key 的所有字段和值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Ehincrby key field increment\u003C/td\u003E\n\u003Ctd\u003E为哈希表 key 中的指定字段的整数值加上增量 increment 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ehincrbyfloat key field increment\u003C/td\u003E\n\u003Ctd\u003E为哈希表 key 中的指定字段的浮点数值加上增量 increment 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Ehkeys key\u003C/td\u003E\n\u003Ctd\u003E获取所有哈希表中的字段\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ehlen key\u003C/td\u003E\n\u003Ctd\u003E获取哈希表中字段的数量\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Ehmget key field1 [field2]\u003C/td\u003E\n\u003Ctd\u003E获取所有给定字段的值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Ehmset key field1 value1 [field2 value2 ]\u003C/td\u003E\n\u003Ctd\u003E同时将多个 field-value (域-值)对设置到哈希表 key 中。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Ehset key field value\u003C/td\u003E\n\u003Ctd\u003E将哈希表 key 中的字段 field 的值设为 value 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Ehsetnx key field value\u003C/td\u003E\n\u003Ctd\u003E只有在字段 field 不存在时，设置哈希表字段的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Ehvals key\u003C/td\u003E\n\u003Ctd\u003E获取哈希表中所有值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Ehscan key cursor [match pattern] [count count]\u003C/td\u003E\n\u003Ctd\u003E迭代哈希表中的键值对。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"1.2.2 哨兵","pId":"e3fc66b","name":"1.2.2 哨兵","parent":"四、数据库/01 redis/1.2 redis 高级","order":2,"sort_id":1024354,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/kerwinC/p/6069864.html\"\u003Eredis主从+哨兵模式\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"https://segmentfault.com/a/1190000002680804\"\u003ERedis Sentinel机制与用法\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1修改sentinelconf-配置\" class=\"anchor\" href=\"#1%E4%BF%AE%E6%94%B9sentinelconf-%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E（1）修改sentinel.conf 配置\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E复制sentinel.conf 配置文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-4.0.11]# cd /usr/local/redis-4.0.11/\n[root@localhost redis-4.0.11]# cp sentinel.conf sentinel.conf.bakcp sentinel.conf sentinel.conf.bak\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改sentinel.conf 配置\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /opt/redis/conf/sentinel.conf\n\n##sentinel for  10.0.0.10 ,its slave is 10.0.0.20\n#master1\n\n# 配置哨兵端口号\nport 26383\n\ndir /usr/local/redis-4.0.11/sentinel-dir\n\n# sentinel monitor 监控的master的名称 ip 端口 确认master死亡所需哨兵的个数\nsentinel monitor master1 192.168.222.132 6379 2\n\n# \nsentinel down-after-milliseconds master1 30000\nsentinel failover-timeout master1 120000\nsentinel parallel-syncs master1 1\n#sentinel auth-pass mymaster 123456　　#如果你的redis集群有密码\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关闭相关防火墙，或者开放端口\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Ca href=\"https://gitee.com/efrans/dashboard/wikis/efrans%2Fsb?doc_id=154819\u0026amp;sort_id=1024065\"\u003Ecentos7 设置防火墙\u003C/a\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动 Sentinel\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eredis-sentinel /path/to/sentinel.conf\n\n或者\n\nredis-server /path/to/sentinel.conf --sentinel\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003EMaster-\u0026gt;Slave-\u0026gt;Sentinel,要确保按照这个顺序依次启动。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3配置说明\" class=\"anchor\" href=\"#3%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E（3）配置说明\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel monitor mymaster 127.0.0.1 6379 2\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003E这一行代表sentinel监控的master的名字叫做mymaster,地址为127.0.0.1:6379，行尾最后的一个2代表什么意思呢？我们知道，网络是不可靠的，有时候一个sentinel会因为网络堵塞而误以为一个master redis已经死掉了，当sentinel集群式，解决这个问题的方法就变得很简单，只需要多个sentinel互相沟通来确认某个master是否真的死了，这个2代表，当集群中有2个sentinel认为master死了时，才能真正认为该master已经不可用了。（sentinel集群中各个sentinel也有互相通信，通过gossip协议）。\u003C/p\u003E\n\u003C/blockquote\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel down-after-milliseconds master1 30000\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003Esentinel会向master发送心跳PING来确认master是否存活，如果master在“一定时间范围”内不回应PING 或者是回复了一个错误消息，那么这个sentinel会主观地(单方面地)认为这个master已经不可用了(subjectively down, 也简称为SDOWN)。而这个down-after-milliseconds就是用来指定这个“一定时间范围”的，单位是毫秒。\u003C/p\u003E\n\u003C/blockquote\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel failover-timeout master1 900000\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003E如果sentinel A推荐sentinel B去执行failover，A等待一段时间后再去failover, 因为根据上下文是B failover timeout了, 之后A再去进行一次。\u003C/p\u003E\n\u003C/blockquote\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel parallel-syncs master1 1\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003E在发生failover主备切换时，这个选项指定了最多可以有多少个slave同时对新的master进行同步，这个数字越小，完成failover所需的时间就越长，但是如果这个数字越大，就意味着越多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave处于不能处理命令请求的状态\u003C/p\u003E\n\u003C/blockquote\u003E"},{"id":"1.2.3.4 启停脚本","pId":"c07e325","name":"1.2.3.4 启停脚本","parent":"四、数据库/01 redis/1.2 redis 高级/1.2.3 集群","order":2,"sort_id":1048315,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-集群操作脚本\" class=\"anchor\" href=\"#1-%E9%9B%86%E7%BE%A4%E6%93%8D%E4%BD%9C%E8%84%9A%E6%9C%AC\"\u003E\u003C/a\u003E1. 集群操作脚本\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E#!/bin/bash\n\n# 配置节点信息\nNODES=(\n  192.168.222.129:7001\n  192.168.222.129:7002\n  192.168.222.129:7003\n  192.168.222.129:7004\n  192.168.222.129:7005\n  192.168.222.129:7006\n)\n\n# Redis 主目录\nREDIS_HOME=/usr/local/deve/soft/redis-4.0.11\n\n# Redis-Cluster 集群主目录\nREDIS_CLUSTER_HOME=/usr/local/deve/soft/redis-cluster\n\n# 当前路径\nPWD=`pwd`\n\n# 启动集群\nstart_cluster(){\n  echo \"==================================== 启动集群 =====================================\"\n  for str in ${NODES[@]};do\n    arr=(${str//:/ })\n    \n    echo \"启动节点 $str\"\n    ${REDIS_HOME}/src/redis-server ${REDIS_CLUSTER_HOME}/${arr[1]}/redis.conf\n  done\n\n  echo \"==================================== 启动成功 =====================================\"  \n    ps -ef | grep redis\n}\n\n# 停止集群\nstop_cluster(){\n  echo \"==================================== 停止集群 =====================================\"\n  for str in ${NODES[@]};do\n    arr=(${str//:/ })\n    \n    echo \"停止节点 $str\"\n    ${REDIS_HOME}/src/redis-cli -c -h ${arr[0]} -p ${arr[1]} shutdown\n  done\n\n  echo \"==================================== 停止成功 =====================================\"  \n    ps -ef | grep redis\n}\n\n\n\n# 清除集群\nclear_cluster(){\n    echo \"=========================== 清除集群开始 ===============\"\n   \n  for str in ${NODES[@]};do\n    arr=(${str//:/ })\n    \n    echo \"停止节点 $str\"\n    ${REDIS_HOME}/src/redis-cli -c -h ${arr[0]} -p ${arr[1]} shutdown\n  \n        echo \"备份节点 $str\"\n        echo `mv ${PWD}/${arr[1]}/node*.conf -f ${PWD}/bak/`\n        echo `mv ${PWD}/${arr[1]}/*.rdb -f ${PWD}/bak/`\n        echo `mv ${PWD}/${arr[1]}/*.aof -f ${PWD}/bak/`\n    done\n\n\n    echo \"=========================== 清除集群成功 ===============\"\n    ps -ef | grep redis\n}\n\n\n# 重建集群\nbuild_cluster(){\n  echo \"启动集群\"\n  start_cluster    \n    \n    echo \"==================================== 重建集群 =====================================\"\n    /usr/local/deve/soft/redis-4.0.11/src/redis-trib.rb  create  --replicas 1 ${NODES[*]} \n    echo \"==================================== 重建成功 =====================================\"  \n    \n  ps -ef | grep redis\n}\n\n\n# 接收输入\nif [[ $1 = 'start' ]];\nthen\n  start_cluster\nelif [[ $1 = 'stop' ]] || [[ $1 = 'shutdown' ]];\nthen\n  stop_cluster\n\nelif [[ $1 = 'clear' ]] || [[ $1 = 'delete' ]];\nthen\n  clear_cluster\n\nelif [[ $1 = 'build' ]] ;\nthen\n  build_cluster\n\nelif [[ $1 = '7001' ]] || [[ $1 = '7002' ]]|| [[ $1 = '7003' ]]|| [[ $1 = '7004' ]]|| [[ $1 = '7005' ]]|| [[ $1 = '7006' ]];\nthen\n  \n  /usr/local/deve/soft/redis-4.0.11/src/redis-cli -c -h 192.168.222.129  -p $1\n\nelse\n  echo \"=========================== 相关命令 ===============\"\n    echo \"build         重建集群\"\n    echo \"clear         删除集群\"\n    echo \"stop          停止集群\"\n    echo \"start         启动集群\"\n    echo \"700*          启动客户端\"\n    echo \"====================================================\"\n\nfi\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.3 java 操作redis集群","pId":"d1f6d69","name":"1.3 java 操作redis集群","parent":"四、数据库/01 redis","order":2,"sort_id":1059881,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.cnblogs.com/xymBlog/p/9303032.html\"\u003E最简单版本(先看这篇)\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/plei_yue/article/details/79362372\"\u003ESpringBoot(六)：SpringBoot整合Redis\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/baidu_41669919/article/details/79148203\"\u003Eredis学习系列(二)--spring boot整合Redis集群\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-pomxml-添加依赖\" class=\"anchor\" href=\"#2-pomxml-%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96\"\u003E\u003C/a\u003E2. pom.xml 添加依赖\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;dependency\u0026gt;\n   \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n   \u0026lt;artifactId\u0026gt;spring-boot-starter-data-redis\u0026lt;/artifactId\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-配置applicationproperties\" class=\"anchor\" href=\"#3-%E9%85%8D%E7%BD%AEapplicationproperties\"\u003E\u003C/a\u003E3. 配置application.properties\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 配置redis\nspring.redis.cluster.nodes=192.168.222.129:7001,192.168.222.129:7002,192.168.222.129:7003,192.168.222.129:7004,192.168.222.129:7005,192.168.222.129:7006\nspring.redis.cluster.max-redirects=100\nspring.redis.cluster.timeout=10000\nspring.redis.jedis.pool.max-active=1000\nspring.redis.jedis.pool.max-idle=30\nspring.redis.jedis.pool.min-idle=5\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-编写config\" class=\"anchor\" href=\"#4-%E7%BC%96%E5%86%99config\"\u003E\u003C/a\u003E4. 编写config\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.i84.redis.config;\n \nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.env.MapPropertySource;\nimport org.springframework.data.redis.connection.RedisClusterConfiguration;\nimport org.springframework.data.redis.connection.RedisConnectionFactory;\nimport org.springframework.data.redis.connection.RedisNode;\nimport org.springframework.data.redis.connection.jedis.JedisClientConfiguration;\nimport org.springframework.data.redis.connection.jedis.JedisClusterConnection;\nimport org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;\nimport org.springframework.data.redis.serializer.StringRedisSerializer;\n\nimport java.io.Serializable;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n *  \n * @version 0.1\n * @since 11/28/18\n */\n@Configuration\npublic class JedisClusterConf {\n\n    @Value(\"${spring.redis.cluster.nodes}\")\n    private String clusterNodes ;\n\n\n    @Value(\"${spring.redis.cluster.max-redirects}\")\n    private int maxRedirects ;\n\n    @Value(\"${spring.redis.cluster.timeout}\")\n    private int timeout ;\n\n    @Value(\"${spring.redis.jedis.pool.max-active}\")\n    private int maxActive ;\n\n\n    @Value(\"${spring.redis.jedis.pool.max-idle}\")\n    private int maxIdle ;\n\n    @Value(\"${spring.redis.jedis.pool.min-idle}\")\n    private int minIdle ;\n \n    @Bean\n    public RedisConnectionFactory myLettuceConnectionFactory() {\n\n        Map\u0026lt;String, Object\u0026gt; source = new HashMap\u0026lt;String, Object\u0026gt;();\n        source.put(\"spring.redis.cluster.nodes\", clusterNodes);\n        source.put(\"spring.redis.cluster.timeout\", timeout);\n        source.put(\"spring.redis.cluster.max-redirects\", maxRedirects);\n\n        RedisClusterConfiguration redisClusterConfiguration;\n        redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource(\"RedisClusterConfiguration\", source));\n        return new LettuceConnectionFactory(redisClusterConfiguration);\n    }\n\n\n    @Bean\n    public RedisTemplate\u0026lt;String, Serializable\u0026gt; redisTemplate() {\n        RedisTemplate\u0026lt;String, Serializable\u0026gt; template = new RedisTemplate\u0026lt;String, Serializable\u0026gt;();\n        template.setKeySerializer(new StringRedisSerializer());\n        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());\n        template.setConnectionFactory(myLettuceConnectionFactory());\n        return template;\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-使用\" class=\"anchor\" href=\"#5-%E4%BD%BF%E7%94%A8\"\u003E\u003C/a\u003E5. 使用\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E@Autowired\nprivate RedisTemplate redisTemplate;\n\n@Test\npublic void redisTemplate() throws Exception {\n    redisTemplate.opsForValue().set(\"author\", \"fff\");\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以关掉节点测试取值是否正常\u003C/li\u003E\n\u003Cli\u003E可以多设置几个值，看能不能设值到不同节点\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.2 常用命令","pId":"cd26332","name":"2.2 常用命令","parent":"四、数据库/02 oracle","order":2,"sort_id":1130005,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch4\u003E\n\u003Ca id=\"1查看数据库是否为cdb\" class=\"anchor\" href=\"#1%E6%9F%A5%E7%9C%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E6%98%AF%E5%90%A6%E4%B8%BAcdb\"\u003E\u003C/a\u003E1.查看数据库是否为CDB\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eselect name, decode(cdb, 'YES', 'Multitenant Option enabled', 'Regular 12c Database: ') \"Multitenant Option\" , open_mode, con_id from v$database;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003EYES表示该数据库是CDB,如果是NO表示是NO-CDB(普通数据库)\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2查看当前容器container\" class=\"anchor\" href=\"#2%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E5%AE%B9%E5%99%A8container\"\u003E\u003C/a\u003E2.查看当前容器（Container）\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eselect sys_context('userenv', 'con_name') \"Container DB\" from dual;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3查看cdb容器中的pdbs信息\" class=\"anchor\" href=\"#3%E6%9F%A5%E7%9C%8Bcdb%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84pdbs%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E3.查看CDB容器中的PDBS信息\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eselect con_id, dbid, guid, name , open_mode from v$pdbs;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4启动pdb数据库要用sysdba启动-sys\" class=\"anchor\" href=\"#4%E5%90%AF%E5%8A%A8pdb%E6%95%B0%E6%8D%AE%E5%BA%93%E8%A6%81%E7%94%A8sysdba%E5%90%AF%E5%8A%A8-sys\"\u003E\u003C/a\u003E4.启动PDB数据库（要用sysdba启动-sys）\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Ealter pluggable database PDBEPPS open;\n\nalter PLUGGABLE DATABASE PDBGZFBC SAVE STATE;--保存开启状态\n\nalter pluggable database PDBEPPS close;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"5在容器间切换\" class=\"anchor\" href=\"#5%E5%9C%A8%E5%AE%B9%E5%99%A8%E9%97%B4%E5%88%87%E6%8D%A2\"\u003E\u003C/a\u003E5.在容器间切换\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Ealter session set container=PDBEPPS;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"6删除pdb\" class=\"anchor\" href=\"#6%E5%88%A0%E9%99%A4pdb\"\u003E\u003C/a\u003E6.删除pdb\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003E--与删除表空间类似，可以级联删除数据文件\ndrop pluggable database pdb2;\ndrop pluggable database pdb2 including datafiles;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"7unplug\" class=\"anchor\" href=\"#7unplug\"\u003E\u003C/a\u003E7.unplug\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003E--unplug后pdb只能mount不能open\nalter pluggable database pdb2 unplug into '/tmp/pdb2.xml';\n\n--unplug后删除pdb，再使用xml文件加回pdb\ndrop pluggable database pdb2;\ncreate pluggable database pdb2 using '/tmp/pdb2.xml' nocopy; \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003ESQL\u0026gt; select name, cdb, open_mode, con_id from v$database;\nSQL\u0026gt; select sys_context('userenv', 'con_name') \"Container DB\" from dual;\nSQL\u0026gt; select con_id, dbid, guid, name, open_mode from v$pdbs;\nSQL\u0026gt; SELECT * FROM v$instance;\nSQL\u0026gt; SELECT * FROM v$database;\nSQL\u0026gt; SELECT * FROM dba_data_files;\nSQL\u0026gt; SELECT * FROM dba_temp_files;\nSQL\u0026gt; SELECT * FROM dba_tablespaces;\nSQL\u0026gt; SELECT * FROM v$parameter;\nSQL\u0026gt; SELECT * FROM v$parameter2;\nSQL\u0026gt; SELECT * FROM v$controlfile;\nSQL\u0026gt; SELECT * FROM v$log;\nSQL\u0026gt; SELECT * FROM v$logfile ORDER BY group# ASC;\nSQL\u0026gt; SELECT THREAD#,SEQUENCE#,NAME,ROUND(BLOCKS * BLOCK_SIZE / 1024 / 1024) AS \"SIZE(M)\",COMPLETION_TIME,DELETED,ARCHIVED FROM V$ARCHIVED_LOG;\nSQL\u0026gt; SELECT * FROM DBA_USERS WHERE ACCOUNT_STATUS = 'OPEN';\nSQL\u0026gt; SELECT username, ACCOUNT_STATUS, CREATED, CON_ID FROM CDB_USERS WHERE account_status='OPEN' ORDER BY CON_ID ASC;\nSQL\u0026gt; SELECT GRANTEE, PRIVILEGE, CON_ID FROM CDB_SYS_PRIVS WHERE GRANTEE = 'PDB_DBA';\nSQL\u0026gt; SELECT * FROM CDB_SYS_PRIVS WHERE GRANTEE = 'PDB_ADMIN';\nSQL\u0026gt; SELECT INSTANCE_NAME,STATUS,INSTANCE_ROLE FROM V$INSTANCE;\nSQL\u0026gt; SELECT * FROM v$asm_disk;\nSQL\u0026gt; SELECT * FROM v$asm_diskgroup;\nSQL\u0026gt; alter session set container=ORCLPDB;\nSQL\u0026gt; alter session set container=CDB$ROOT;\nSQL\u0026gt; show con_name;\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.4 脏读","pId":"2fc41b2","name":"1.4 脏读","parent":"一、并发编程/01  线程基础","order":3,"sort_id":679743,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo脏读\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E8%84%8F%E8%AF%BB\"\u003E\u003C/a\u003E1. 示例demo（脏读）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 业务整体需要使用完整的synchronized，保持业务的原子性。\n * @author alienware\n *\n */\npublic class DirtyRead {\n\n\tprivate String username = \"bjsxt\";\n\tprivate String password = \"123\";\n\t\n\tpublic synchronized void setValue(String username, String password){\n\t\tthis.username = username;\n\t\t\n\t\ttry {\n\t\t\tThread.sleep(2000);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\t\n\t\tthis.password = password;\n\t\t\n\t\tSystem.out.println(\"setValue最终结果：username = \" + username + \" , password = \" + password);\n\t}\n\t\n\tpublic void getValue(){\n\t\tSystem.out.println(\"getValue方法得到：username = \" + this.username + \" , password = \" + this.password);\n\t}\n\t\n\t\n\tpublic static void main(String[] args) throws Exception{\n\t\t\n\t\tfinal DirtyRead dr = new DirtyRead();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tdr.setValue(\"z3\", \"456\");\t\t\n\t\t\t}\n\t\t});\n\t\tt1.start();\n\t\tThread.sleep(1000);\n\t\t\n\t\tdr.getValue();\n\t}\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"getValue\"方法不加synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/145839_2f05db74_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"getValue\"方法加上synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/145914_cad59324_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-案例说明\" class=\"anchor\" href=\"#2-%E6%A1%88%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 案例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，dr对象可以以异步的方式调用对象中的非synchronized修饰的方法\u003C/li\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，dr对象如果在这个时候调用对象中的同步（synchronized）方法则需等待，也就是同步\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"75d372a","pId":"77fbb9c","name":"2.4 高并发容器","parent":"一、并发编程/02 多线程通信","sort_id":700005,"order":3,"isParent":true,"extname":null,"open":false},{"id":"2.5.3 FixedThreadPool","pId":"b6b90b0","name":"2.5.3 FixedThreadPool","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":3,"sort_id":735206,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建可重用且固定线程数的线程池\u003C/li\u003E\n\u003Cli\u003E如果线程池中的所有线程都处于活动状态，此时再提交任务就在队列中等待，直到有可用线程；\u003C/li\u003E\n\u003Cli\u003E如果线程池中的某个线程由于异常而结束时，线程池就会再补充一条新线程。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic static ExecutorService newFixedThreadPool(int nThreads) {\n    return new ThreadPoolExecutor(nThreads, nThreads,\n                                  0L, TimeUnit.MILLISECONDS,\n                                  //使用一个基于FIFO排序的阻塞队列，在所有corePoolSize线程都忙时新任务将在队列中等待\n                                  new LinkedBlockingQueue\u0026lt;Runnable\u0026gt;());\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E使用的是LinkedBlockingQueue无界队列，主要问题是堆积的请求处理队列可能会耗费非常大的内存，甚至OOM\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n\n/**\n * 测试testFixedThreadPool\n */\npublic static void testFixedThreadPool() {\n    ExecutorService executorService = Executors.newFixedThreadPool(2);\n\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.execute(new TempTask(i));\n    }\n\n    executorService.shutdown();\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/111352_a2851650_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"2.6.4 Semaphore 信号量（限流）","pId":"3b56f09","name":"2.6.4 Semaphore 信号量（限流）","parent":"一、并发编程/02 多线程通信/2.6 concurrent工具类","order":3,"sort_id":748710,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.height.concurrent019.fxz;\n\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Random;\nimport java.util.concurrent.Semaphore;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/11\n */\npublic class TestSemaphore {\n\n\n    public static void main(String[] args) {\n\n        final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n        // 只运行5个线程同时进行\n        Semaphore semaphore = new Semaphore(5);\n\n        for (int i = 0; i \u0026lt; 20; i++) {\n            final int INDEX = i;\n\n            new Thread(() -\u0026gt; {\n                try {\n                    // 获取许可\n                    semaphore.acquire();\n                    Thread.sleep(1000);\n                    System.out.println(format.format(new Date()) + \" 线程\" + INDEX + \"开始\");\n                    // 访问结束，释放\n                    semaphore.release();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }).start();\n        }\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0925/120014_3504792a_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以实现限流\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.8.3 RingBuffer 单独使用","pId":"6619c4c","name":"2.8.3 RingBuffer 单独使用","parent":"一、并发编程/02 多线程通信/2.8 disruptor","order":3,"sort_id":822721,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-构造说明\" class=\"anchor\" href=\"#1-%E6%9E%84%E9%80%A0%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 构造说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eringbuffer\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建单生产者的ringbuffer\n * @param factory         : 事件工厂\n * @param bufferSize      : 缓冲大小\n * @param waitStrategy    : 等待策略\n */\nRingBuffer\u0026lt;OrderEvent\u0026gt; ringBuffer = RingBuffer.createSingleProducer(new EventFactory\u0026lt;OrderEvent\u0026gt;() {\n    @Override\n    public OrderEvent newInstance() {\n        return new OrderEvent();\n    }\n}, BUFFER_SIZE, new YieldingWaitStrategy());\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EBatchEventProcessor\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建消息处理器\n * @param dataProvider         : 事件工厂\n * @param sequenceBarrier      : 缓冲大小\n * @param eventHandler         : 等待策略\n */\nBatchEventProcessor\u0026lt;OrderEvent\u0026gt; processor = new BatchEventProcessor\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new EventHandler\u0026lt;OrderEvent\u0026gt;() {\n    @Override\n    public void onEvent(OrderEvent orderEvent, long l, boolean b) throws Exception {\n        System.out.println(orderEvent);\n    }\n});\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EWorkerPool\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建工作池\n * @param   ringBuffer          缓存\n * @param   sequenceBarrier     障碍\n * @param   exceptionHandler    异常处理\n * @param   workHandlers....    事件消费\n */\nWorkerPool\u0026lt;OrderEvent\u0026gt; workerPool = new WorkerPool\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), new WorkHandler\u0026lt;OrderEvent\u0026gt;() {\n    @Override\n    public void onEvent(OrderEvent orderEvent) throws Exception {\n        System.out.println(orderEvent);\n    }\n});\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例demo\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E2. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.*;\n\nimport java.util.Random;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/28\n */\npublic class RingMain {\n\n    // 缓冲大小\n    final static int BUFFER_SIZE = 1024;\n\n    // 线程大小\n    final static int THREAD_NUMBERS = 4;\n\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n\n        /**\n         * 创建单生产者的ringbuffer\n         * @param factory         : 事件工厂\n         * @param bufferSize      : 缓冲大小\n         * @param waitStrategy    : 等待策略\n         */\n        RingBuffer\u0026lt;OrderEvent\u0026gt; ringBuffer = RingBuffer.createSingleProducer(new EventFactory\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public OrderEvent newInstance() {\n                return new OrderEvent();\n            }\n        }, BUFFER_SIZE, new YieldingWaitStrategy());\n\n\n        //创建SequenceBarrier\n        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();\n\n        /**\n         * 创建消息处理器\n         * @param dataProvider         : 事件工厂\n         * @param sequenceBarrier      : 缓冲大小\n         * @param eventHandler         : 等待策略\n         */\n        BatchEventProcessor\u0026lt;OrderEvent\u0026gt; processor = new BatchEventProcessor\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new EventHandler\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public void onEvent(OrderEvent orderEvent, long l, boolean b) throws Exception {\n                System.out.println(orderEvent);\n            }\n        });\n\n\n        //这一步的目的就是把消费者的位置信息引用注入到生产者    如果只有一个消费者的情况可以省略\n        ringBuffer.addGatingSequences(processor.getSequence());\n\n\n        // 创建线程池\n        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUMBERS);\n        //把消息处理器提交到线程池\n        executorService.submit(processor);\n\n        // 生产数据\n        Future\u0026lt;Void\u0026gt; future = executorService.submit(new Callable\u0026lt;Void\u0026gt;() {\n            @Override\n            public Void call() throws Exception {\n                long seq = 0 ;\n                for (int i = 0 ; i \u0026lt; 10 ; i++) {\n                    seq = ringBuffer.next() ;\n                    ringBuffer.get(seq).setName(\"name_\" + i);\n                    ringBuffer.get(seq).setPrice(new Random().nextInt(100));\n                    ringBuffer.publish(seq);\n                }\n                return null;\n            }\n        });\n\n        //等待生产者结束\n        future.get();\n\n        //等上1秒，等消费都处理完成\n        Thread.sleep(1000);\n\n        //通知事件(或者说消息)处理器 可以结束了（并不是马上结束!!!）\n        processor.halt();\n\n        //终止线程\n        executorService.shutdown();\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport com.lmax.disruptor.*;\n\nimport java.util.Random;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/28\n */\npublic class RingMain2 {\n\n    // 缓冲大小\n    final static int BUFFER_SIZE = 1024;\n\n    // 线程大小\n    final static int THREAD_NUMBERS = 4;\n\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n        RingBuffer\u0026lt;OrderEvent\u0026gt; ringBuffer = RingBuffer.createSingleProducer(new EventFactory\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public OrderEvent newInstance() {\n                return new OrderEvent();\n            }\n        }, BUFFER_SIZE, new YieldingWaitStrategy());\n\n        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();\n\n        // 线程池\n        ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMBERS);\n\n        /**\n         * 创建工作池\n         * @param   ringBuffer          缓存\n         * @param   sequenceBarrier     障碍\n         * @param   exceptionHandler    异常处理\n         * @param   workHandlers....    事件消费\n         */\n        WorkerPool\u0026lt;OrderEvent\u0026gt; workerPool = new WorkerPool\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), new WorkHandler\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public void onEvent(OrderEvent orderEvent) throws Exception {\n                System.out.println(orderEvent);\n            }\n        });\n\n        workerPool.start(executor);\n\n        //下面这个生产8个数据\n        long seq = -1;\n        for (int i = 0; i \u0026lt; 8; i++) {\n            seq = ringBuffer.next();\n            ringBuffer.get(seq).setName(\"name_\" + i);\n            ringBuffer.get(seq).setPrice(new Random().nextInt(100));\n            ringBuffer.publish(seq);\n        }\n\n        Thread.sleep(1000);\n        workerPool.halt();\n        executor.shutdown();\n\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.3  安装python3","pId":"7a86ec7","name":"1.3  安装python3","parent":"三、linux /01 软件安装","order":3,"sort_id":987024,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考链接\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5\"\u003E\u003C/a\u003E1. 参考链接\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"blogs.com/dongml/p/8719421.html\"\u003Ecentos7 python3安装\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-安装准备\" class=\"anchor\" href=\"#2-%E5%AE%89%E8%A3%85%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E2. 安装准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ecentos7原本就安装了Python2，而且这个Python2不能被删除\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1030/160808_f8558c4c_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装相关软件包\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esudo yum update -y  # 更新系统软件包\nsudo yum groupinstall -y \"development tools\" \nsudo yum install zlib zlib-devel bzip2-devel openssl openssl-devel libffi-devel ncurses-devel xz-devel python3-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel expat-devel\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E下载最新版本python\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E(1) \u003Ca href=\"https://www.python.org/ftp/python/3.7.1/Python-3.7.1.tgz\"\u003Epython3.7.1 下载\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E(2) \u003Ca href=\"https://www.python.org/downloads/\"\u003Epython官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-安装python\" class=\"anchor\" href=\"#3-%E5%AE%89%E8%A3%85python\"\u003E\u003C/a\u003E3. 安装python\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E相关命令:\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 解压\n[root@localhost bin]# tar -xvf Python-3.7.1.tgz\n[root@localhost bin]# cd Python-3.7.1/\n\n# 配置安装目录\n[root@localhost bin]# ./configure --prefix=/usr/local/deve/soft/python3\n\n# 编译安装\n[root@localhost bin]# make \u0026amp;\u0026amp; make install\n\n# 设置软链\n[root@localhost bin]# ln -s /usr/local/deve/soft/python3/bin/python3 /usr/bin/python3\n[root@localhost bin]# ln -s /usr/local/deve/soft/python3/bin/pip3 /usr/bin/pip3\n\n# 安装virtualenv\n[root@localhost bin]# ./pip3 install virtualenv\n[root@localhost bin]# ln -s /usr/local/deve/soft/python3/bin/virtualenv /usr/bin/venv3\n\n# 验证是否成功\n[root@localhost bin]# python3\n[root@localhost bin]# pip3 -V\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1030/165113_a09113cc_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E输入pip3 -V查看pip版本,安装成功则正确显示版本\u003C/p\u003E"},{"id":"2.4 网络配置","pId":"6275c3c","name":"2.4 网络配置","parent":"三、linux /02 系统操作","order":3,"sort_id":987035,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-切换到root用户\" class=\"anchor\" href=\"#1-%E5%88%87%E6%8D%A2%E5%88%B0root%E7%94%A8%E6%88%B7\"\u003E\u003C/a\u003E1. 切换到root用户\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esu root\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-编辑网卡信息\" class=\"anchor\" href=\"#2-%E7%BC%96%E8%BE%91%E7%BD%91%E5%8D%A1%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E2. 编辑网卡信息\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/sysconfig/network-scripts/ifcfg-eth0\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-设置为动态获取\" class=\"anchor\" href=\"#3-%E8%AE%BE%E7%BD%AE%E4%B8%BA%E5%8A%A8%E6%80%81%E8%8E%B7%E5%8F%96\"\u003E\u003C/a\u003E3. 设置为动态获取\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EDEVICE=\"eth0\"\nBOOTPROTO=\"dhcp\"\nHWADDR=\"00:0C:29:86:A6:11\"\nIPV6INIT=\"yes\"\nNM_CONTROLLED=\"yes\"\nONBOOT=\"yes\"\nTYPE=\"Ethernet\"\nUUID=\"948534ec-43f8-4da1-8ba7-d6ff0df8fb55\"\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-设置为静态ip\" class=\"anchor\" href=\"#4-%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%9D%99%E6%80%81ip\"\u003E\u003C/a\u003E4. 设置为静态ip\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EDEVICE=\"eth0\"\nBOOTPROTO=\"static\"\nHWADDR=\"00:0C:29:86:A6:11\"\nIPV6INIT=\"yes\"\nNM_CONTROLLED=\"yes\"\nONBOOT=\"yes\"\nTYPE=\"Ethernet\"\nUUID=\"948534ec-43f8-4da1-8ba7-d6ff0df8fb55\"\nIPADDR=192.168.222.100\nNEWMASK=255.255.255.0\nGATEWAY=192.168.222.2\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-配置dns-vim-etcresolvconf\" class=\"anchor\" href=\"#5-%E9%85%8D%E7%BD%AEdns-vim-etcresolvconf\"\u003E\u003C/a\u003E5. 配置DNS vim /etc/resolv.conf\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Enameserver 192.168.222.2\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-重启网络\" class=\"anchor\" href=\"#6-%E9%87%8D%E5%90%AF%E7%BD%91%E7%BB%9C\"\u003E\u003C/a\u003E6. 重启网络\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eservice network restart\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"8b32ab8","pId":"2116d9f","name":"03 常用命令","parent":"三、linux ","sort_id":987036,"order":3,"isParent":true,"extname":null,"open":false},{"id":"3. Excel 读写","pId":"97a5782","name":"3. Excel 读写","parent":"九、工具类","order":3,"sort_id":1224890,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1参考资料\" class=\"anchor\" href=\"#1%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1.参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"http://likaixuan.top/excelUtil#\"\u003EExcelutil\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-引入pom\" class=\"anchor\" href=\"#2-%E5%BC%95%E5%85%A5pom\"\u003E\u003C/a\u003E2. 引入pom\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;dependency\u0026gt;\n    \u0026lt;groupId\u0026gt;net.oschina.likaixuan\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;excelutil\u0026lt;/artifactId\u0026gt;\n    \u0026lt;version\u0026gt;2.0.2\u0026lt;/version\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-读取excel\" class=\"anchor\" href=\"#3-%E8%AF%BB%E5%8F%96excel\"\u003E\u003C/a\u003E3. 读取Excel\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EString keyValue =\"手机名称:phoneName,颜色:color,售价:price\"; \nList\u0026lt;PhoneModel\u0026gt; list=ExcelUtil.readXls(\"C://test.xlsx\",ExcelUtil.getMap(keyValue),\"com.lkx.model.PhoneModel\");\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-写入excel\" class=\"anchor\" href=\"#3-%E5%86%99%E5%85%A5excel\"\u003E\u003C/a\u003E3. 写入Excel\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EString keyValue =\"手机名称:phoneName,颜色:color,售价:price\"; \nExcelUtil.exportExcel(\"d:/testsss.xls\",keyValue,list,\"com.lkx.model.PhoneModel\");\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"5.1.4 参数配置","pId":"008a6af","name":"5.1.4 参数配置","parent":"五、java 虚拟机/01 JVM 结构","order":3,"sort_id":1005014,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E  \u003Ca href=\"https://blog.csdn.net/see__you__again/article/details/51998038\"\u003EJVM参数设置、分析\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-常见参数配置\" class=\"anchor\" href=\"#2-%E5%B8%B8%E8%A7%81%E5%8F%82%E6%95%B0%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E2. 常见参数配置\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E说明\u003C/th\u003E\n\u003Cth\u003E默认配置\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xms\u003C/td\u003E\n\u003Ctd\u003E初始堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmx\u003C/td\u003E\n\u003Ctd\u003E最大堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmn\u003C/td\u003E\n\u003Ctd\u003E配置新生代大小，对系统性能及GC有比较大影响，一般配置在堆大小的1/4到1/3左右\u003C/td\u003E\n\u003Ctd\u003E1/3\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:PermSize\u003C/td\u003E\n\u003Ctd\u003E方法区大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:MaxPermSize\u003C/td\u003E\n\u003Ctd\u003E方法区最大大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:NewRatio\u003C/td\u003E\n\u003Ctd\u003E老年代/新生代\u003C/td\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:SurvivorRatio\u003C/td\u003E\n\u003Ctd\u003EEden区/Form区的比例=EDEN/FROM=EDEN/TO\u003C/td\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xss\u003C/td\u003E\n\u003Ctd\u003E指定线程最大栈空间\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintCommandLineFlags\u003C/td\u003E\n\u003Ctd\u003E输出参数信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGC\u003C/td\u003E\n\u003Ctd\u003E打印GC日志\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGCDetails\u003C/td\u003E\n\u003Ctd\u003E打印GC日志详细信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"1.1.4 list 类型命令","pId":"ed9af11","name":"1.1.4 list 类型命令","parent":"四、数据库/01 redis/1.1 Redis 命令","order":3,"sort_id":995337,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"redis-列表list\" class=\"anchor\" href=\"#redis-%E5%88%97%E8%A1%A8list\"\u003E\u003C/a\u003ERedis 列表(List)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003ERedis列表是简单的字符串列表，按照插入顺序排序。你可以添加一个元素到列表的头部（左边）或者尾部（右边）\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Eblpop key1 [key2 ] timeout\u003C/td\u003E\n\u003Ctd\u003E移出并获取列表的第一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ebrpop key1 [key2 ] timeout\u003C/td\u003E\n\u003Ctd\u003E移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Ebrpoplpush source destination timeout\u003C/td\u003E\n\u003Ctd\u003E从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它； 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Elindex key index\u003C/td\u003E\n\u003Ctd\u003E通过索引获取列表中的元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Elinsert key before\u003C/td\u003E\n\u003Ctd\u003Eafter pivot value  在列表的元素前或者后插入元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ellen key\u003C/td\u003E\n\u003Ctd\u003E获取列表长度\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Elpop key\u003C/td\u003E\n\u003Ctd\u003E移出并获取列表的第一个元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Elpush key value1 [value2]\u003C/td\u003E\n\u003Ctd\u003E将一个或多个值插入到列表头部\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Elpushx key value\u003C/td\u003E\n\u003Ctd\u003E将一个值插入到已存在的列表头部\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Elrange key start stop\u003C/td\u003E\n\u003Ctd\u003E获取列表指定范围内的元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Elrem key count value\u003C/td\u003E\n\u003Ctd\u003E移除列表元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Elset key index value\u003C/td\u003E\n\u003Ctd\u003E通过索引设置列表元素的值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Eltrim key start stop\u003C/td\u003E\n\u003Ctd\u003E对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Erpop key\u003C/td\u003E\n\u003Ctd\u003E移除列表的最后一个元素，返回值为移除的元素。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Erpoplpush source destination\u003C/td\u003E\n\u003Ctd\u003E移除列表的最后一个元素，并将该元素添加到另一个列表并返回\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Erpush key value1 [value2]\u003C/td\u003E\n\u003Ctd\u003E在列表中添加一个或多个值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E17\u003C/td\u003E\n\u003Ctd\u003Erpushx key value\u003C/td\u003E\n\u003Ctd\u003E为已存在的列表添加值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"c07e325","pId":"e3fc66b","name":"1.2.3 集群","parent":"四、数据库/01 redis/1.2 redis 高级","sort_id":1047682,"order":3,"isParent":true,"extname":null,"open":false},{"id":"1.2.3.5 添加节点","pId":"c07e325","name":"1.2.3.5 添加节点","parent":"四、数据库/01 redis/1.2 redis 高级/1.2.3 集群","order":3,"sort_id":1057853,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"参考资料\" class=\"anchor\" href=\"#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/Howinfun/article/details/81938161\"\u003ERedis集群添加和删除节点（主和从）\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-添加主节点\" class=\"anchor\" href=\"#1-%E6%B7%BB%E5%8A%A0%E4%B8%BB%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E1. 添加主节点\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-cluster]# /usr/local/deve/soft/redis-4.0.11/src/redis-server 7007/redis.conf  \n[root@localhost src]# ./redis-trib.rb add-node 192.168.222.129:7007 192.168.222.129:7001\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E刚加入的节点是无solt（槽）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-为主节点分配槽\" class=\"anchor\" href=\"#2-%E4%B8%BA%E4%B8%BB%E8%8A%82%E7%82%B9%E5%88%86%E9%85%8D%E6%A7%BD\"\u003E\u003C/a\u003E2. 为主节点分配槽\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# ./redis-trib.rb reshard 192.168.222.129:7007\n\nHow many slots do you want to move (from 1 to 16384)?  输入要分配的槽数量\nWhat is the receiving node ID? 输入新节点的ID\nPlease enter all the source node IDs.\nType 'all' to use all the nodes as source nodes for the hash slots.\nType 'done' once you entered all the source nodes IDs.\nSource node #1:all\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-添加从节点\" class=\"anchor\" href=\"#3-%E6%B7%BB%E5%8A%A0%E4%BB%8E%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E3. 添加从节点\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E新增节点\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-cluster]# /usr/local/deve/soft/redis-4.0.11/src/redis-server 7008/redis.conf \n[root@localhost src]# ./redis-trib.rb add-node 192.168.222.129:7008 192.168.222.129:7001\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E指定主节点\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 登录7008节点\n[root@localhost src]# ./redis-cli -c -h 192.168.222.129 -p 7008\n192.168.222.129:7008\u0026gt; cluster replicate 0e2ba9c12d9c211d07530fc9242c187d175ceedb\nOK\n192.168.222.129:7008\u0026gt; cluster nodes\n24ef75ce1385a29c11e1e970143670630a345711 192.168.222.129:7002@17002 master - 0 1543310055598 2 connected 5461-10922\nbfa68ee0d6335ebd93c8bc58f73dd67c6e67c353 192.168.222.129:7001@17001 master - 0 1543310056000 1 connected 0-5460\n5b98ed16b3ead28b072762650450b9441296ab18 192.168.222.129:7006@17006 slave bfa68ee0d6335ebd93c8bc58f73dd67c6e67c353 0 1543310055000 1 connected\n3875de68fe213d19fb8e64311031b0ebdd63e566 192.168.222.129:7004@17004 slave 24ef75ce1385a29c11e1e970143670630a345711 0 1543310055000 2 connected\n1e61f26a3f8057264c956c4d02f6f57abf4d2d67 192.168.222.129:7003@17003 master - 0 1543310055000 3 connected 11923-16383\n287476ede647ca6eca1f2da01f1bb5efb49af4a2 192.168.222.129:7008@17008 myself,slave 0e2ba9c12d9c211d07530fc9242c187d175ceedb 0 1543310056000 0 connected\n267be6e526fde26d544a5e041db560323f037bad 192.168.222.129:7005@17005 slave 1e61f26a3f8057264c956c4d02f6f57abf4d2d67 0 1543310056000 3 connected\n0e2ba9c12d9c211d07530fc9242c187d175ceedb 192.168.222.129:7007@17007 master - 0 1543310056802 7 connected 10923-11922\n192.168.222.129:7008\u0026gt; \n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.4 redis 常见错误","pId":"d1f6d69","name":"1.4 redis 常见错误","parent":"四、数据库/01 redis","order":3,"sort_id":1067923,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1warning-overcommit_memory-is-set-to-0-background-save-may-fail-under-low-memory-condition-to-fix-this-issue-add-vmovercommit_memory--1-to-etcsysctlconf-and-then-reboot-or-run-the-command-sysctl-vmovercommit_memory1-for-this-to-take-effect\" class=\"anchor\" href=\"#1warning-overcommit_memory-is-set-to-0-background-save-may-fail-under-low-memory-condition-to-fix-this-issue-add-vmovercommit_memory--1-to-etcsysctlconf-and-then-reboot-or-run-the-command-sysctl-vmovercommit_memory1-for-this-to-take-effect\"\u003E\u003C/a\u003E1.WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E echo 1 \u0026gt; /proc/sys/vm/overcommit_memory  不需要启机器就生效\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2warning-the-tcp-backlog-setting-of-511-cannot-be-enforced-because-procsysnetcoresomaxconn-is-set-to-the-lower-value-of-128\" class=\"anchor\" href=\"#2warning-the-tcp-backlog-setting-of-511-cannot-be-enforced-because-procsysnetcoresomaxconn-is-set-to-the-lower-value-of-128\"\u003E\u003C/a\u003E2.WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E echo 511 \u0026gt; /proc/sys/net/core/somaxconn\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.3 常见问题","pId":"cd26332","name":"2.3 常见问题","parent":"四、数据库/02 oracle","order":3,"sort_id":1130007,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch4\u003E\n\u003Ca id=\"1-ora-65024\" class=\"anchor\" href=\"#1-ora-65024\"\u003E\u003C/a\u003E1. ora-65024\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201806/06160106_0knG.png\" alt=\"ora-65024 数据库未打开\" title=\"在这里输入图片标题\"\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E启动PDB数据库（要用sysdba启动-sys）\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Ealter pluggable database PDBEPPS open;\n\nalter PLUGGABLE DATABASE PDBGZFBC SAVE STATE;--保存开启状态\n\nalter pluggable database PDBEPPS close;\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.5 串联调用","pId":"2fc41b2","name":"1.5 串联调用","parent":"一、并发编程/01  线程基础","order":4,"sort_id":680333,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo多个同步方法串联调用\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E5%A4%9A%E4%B8%AA%E5%90%8C%E6%AD%A5%E6%96%B9%E6%B3%95%E4%B8%B2%E8%81%94%E8%B0%83%E7%94%A8\"\u003E\u003C/a\u003E1. 示例demo（多个同步方法串联调用）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * synchronized的重入\n * @author alienware\n *\n */\npublic class SyncDubbo1 {\n\n\tpublic synchronized void method1(){\n\t\tSystem.out.println(\"method1..\");\n\t\tmethod2();\n\t}\n\tpublic synchronized void method2(){\n\t\tSystem.out.println(\"method2..\");\n\t\tmethod3();\n\t}\n\tpublic synchronized void method3(){\n\t\tSystem.out.println(\"method3..\");\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal SyncDubbo1 sd = new SyncDubbo1();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tsd.method1();\n\t\t\t}\n\t\t});\n\t\tt1.start();\n\t}\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"b6b90b0","pId":"77fbb9c","name":"2.5 线程池","parent":"一、并发编程/02 多线程通信","sort_id":728970,"order":4,"isParent":true,"extname":null,"open":false},{"id":"2.5.4 SingleThreadExecutor","pId":"b6b90b0","name":"2.5.4 SingleThreadExecutor","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":4,"sort_id":735270,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建一个单线程的Executor，如果该线程因为异常而结束就新建一条线程来继续执行后续的任务\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic static ExecutorService newSingleThreadExecutor() {\n   return new FinalizableDelegatedExecutorService\n                     //corePoolSize和maximumPoolSize都等于，表示固定线程池大小为1\n                        (new ThreadPoolExecutor(1, 1,\n                                                0L, TimeUnit.MILLISECONDS,\n                                                new LinkedBlockingQueue\u0026lt;Runnable\u0026gt;()));\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E使用的是LinkedBlockingQueue无界队列，主要问题是堆积的请求处理队列可能会耗费非常大的内存，甚至OOM\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n/**\n * 测试SingleThreadPool\n */\npublic static void testSingleThreadPool() {\n    ExecutorService executorService = Executors.newSingleThreadExecutor();\n\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.execute(new TempTask(i));\n    }\n\n    executorService.shutdown();\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/111214_4d11eca3_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"2.7 重入锁","pId":"5fc2e0f","name":"2.7 重入锁","parent":"一、并发编程/02 多线程通信/2.7 Lock 锁","order":4,"sort_id":798219,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0925/173137_9be6f511_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"2.8.4 顺序执行","pId":"6619c4c","name":"2.8.4 顺序执行","parent":"一、并发编程/02 多线程通信/2.8 disruptor","order":4,"sort_id":822750,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0930/151758_9fe89070_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.YieldingWaitStrategy;\nimport com.lmax.disruptor.dsl.Disruptor;\nimport com.lmax.disruptor.dsl.ProducerType;\n\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class LineMain {\n\n    private final static int BUFFER_SIZE = 1024;\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n\n        long beginTime = System.currentTimeMillis();\n\n        ExecutorService executorService = Executors.newFixedThreadPool(4);\n\n        // 1. 创建disruptor\n        Disruptor\u0026lt;OrderEvent\u0026gt; disruptor = new Disruptor\u0026lt;OrderEvent\u0026gt;(\n                () -\u0026gt; {\n                    return new OrderEvent();\n                },\n                BUFFER_SIZE,\n                executorService,\n                ProducerType.SINGLE,\n                new YieldingWaitStrategy()\n        );\n\n        // 2. 设置消费顺序（直线顺序消费）\n        disruptor.handleEventsWith(new OrderHandler1())\n                .handleEventsWith(new OrderHandler2())\n                .handleEventsWith(new OrderHandler3());\n\n        // 3. 启动\n        disruptor.start();\n\n        // 4. 生产数据\n        Future\u0026lt;?\u0026gt; future = executorService.submit(() -\u0026gt; {\n            for (int i = 0; i \u0026lt; 5; i++) {\n                disruptor.publishEvent((OrderEvent event, long sequence) -\u0026gt; {\n                    event.setName(\"初始化订单\");\n                    System.out.println(\"初始化订单\");\n                });\n            }\n            return null;\n        });\n\n        // 5. 保证数据生成完成\n        future.get();\n\n        // 6. 关闭资源\n        disruptor.shutdown();\n        executorService.shutdown();\n\n        System.out.println(\"耗时：\" + (System.currentTimeMillis() - beginTime));\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EOrderHandler1\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.EventHandler;\nimport com.lmax.disruptor.WorkHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class OrderHandler1 implements EventHandler\u0026lt;OrderEvent\u0026gt;, WorkHandler\u0026lt;OrderEvent\u0026gt; {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {\n        onEvent(event);\n    }\n\n    @Override\n    public void onEvent(OrderEvent event) throws Exception {\n        event.setName(FORMAT.format(new Date()) + \" 订单 \");\n        System.out.println(FORMAT.format(new Date()) + \" ___   OrderHandler1 处理订单设置订单名 \");\n        Thread.sleep(1000);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EOrderHandler2\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.EventHandler;\nimport com.lmax.disruptor.WorkHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class OrderHandler2 implements EventHandler\u0026lt;OrderEvent\u0026gt;, WorkHandler\u0026lt;OrderEvent\u0026gt; {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {\n        onEvent(event);\n    }\n\n    @Override\n    public void onEvent(OrderEvent event) throws Exception {\n        event.setPrice(100);\n        System.out.println(FORMAT.format(new Date()) + \" ___   OrderHandler2 处理订单设置订单价格 \");\n        Thread.sleep(500);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EOrderHandler3\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.EventHandler;\nimport com.lmax.disruptor.WorkHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Random;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class OrderHandler3 implements EventHandler\u0026lt;OrderEvent\u0026gt;, WorkHandler\u0026lt;OrderEvent\u0026gt; {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {\n        onEvent(event);\n    }\n\n    @Override\n    public void onEvent(OrderEvent event) throws Exception {\n        event.setPrice(100 - new Random().nextInt(1));\n        System.out.println(FORMAT.format(new Date()) + \" ___   OrderHandler3 处理订单随机减 \");\n        Thread.sleep(500);\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E模拟“消费1” -- “消费2” -- “消费3”\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0930/151143_1ac857f0_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"1.4 安装pycharm","pId":"7a86ec7","name":"1.4 安装pycharm","parent":"三、linux /01 软件安装","order":4,"sort_id":987025,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/yaoqiwaimai/article/details/74626851\"\u003Ecentos 7下安装pycharm专业版\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.jetbrains.com/pycharm/download/#section=linux\"\u003Epycharm下载地址\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.cnblogs.com/lenmom/p/9193183.html\"\u003ECentOS 7 创建桌面快捷方式\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-在桌面添加快捷方式\" class=\"anchor\" href=\"#2-%E5%9C%A8%E6%A1%8C%E9%9D%A2%E6%B7%BB%E5%8A%A0%E5%BF%AB%E6%8D%B7%E6%96%B9%E5%BC%8F\"\u003E\u003C/a\u003E2. 在桌面添加快捷方式\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在/usr/share/applications目录下创建以.desktop为后缀的文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 非root用户\nvi /home/fxz/Desktop/eclipse.desktop\n\n# root用户\nvim /usr/share/applications/pycharm.desktop\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E将以下内容写入上面创建的文件中\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E#!/usr/bin/env xdg-open\n[Desktop Entry]\nEncoding=UTF-8\nName=Pycharm\nComment=pycharm-2018.1.1\nExec=/usr/local/deve/soft/pycharm-2018.2.4/bin/pycharm.sh\nIcon=/usr/local/deve/soft/pycharm-2018.2.4/bin/pycharm.png\nTerminal=false\nStartupNotify=true\nType=Application    #快捷方式的类型\nCategories=Application;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003Eps：根据设置不同软件的快捷键，修改下内容即可\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E给文件赋予可执行权限\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Echmod a+x /usr/share/applications/pycharm.desktop\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E点击左上角的位置，找到/usr/share/applications目录下，将会看到你所配置的图标，右击复制到桌面即可。\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1031/105040_743082d0_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\n\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.5 CentOS7图形界面与命令行界面切换","pId":"6275c3c","name":"2.5 CentOS7图形界面与命令行界面切换","parent":"三、linux /02 系统操作","order":4,"sort_id":1023958,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-在命令上输入\" class=\"anchor\" href=\"#1-%E5%9C%A8%E5%91%BD%E4%BB%A4%E4%B8%8A%E8%BE%93%E5%85%A5\"\u003E\u003C/a\u003E1. 在命令上输入\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Einit 3 命令 切换到dos界面\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Einit 5 命令 切换到图形界面\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-修改方法为\" class=\"anchor\" href=\"#2-%E4%BF%AE%E6%94%B9%E6%96%B9%E6%B3%95%E4%B8%BA\"\u003E\u003C/a\u003E2. 修改方法为：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 首先删除已经存在的符号链接：\n\nrm /etc/systemd/system/default.target  \n\n# 默认级别转换为3(文本模式)： \n\nln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target \n 或者默认级别转换为5(图形模式)：\nln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target\n\n# 重启：\nreboot \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-centos7以下的版本\" class=\"anchor\" href=\"#3-centos7%E4%BB%A5%E4%B8%8B%E7%9A%84%E7%89%88%E6%9C%AC\"\u003E\u003C/a\u003E3. centos7以下的版本\u003C/h3\u003E\n\u003Cp\u003E以管理员权限编辑/etc/inittab\n把\nid:5:initdefault:\n改为\nid:3:initdefault:\n就ok。\u003C/p\u003E"},{"id":"54f3dd9","pId":"2116d9f","name":"04  服务器","parent":"三、linux ","sort_id":987053,"order":4,"isParent":true,"extname":null,"open":false},{"id":"008a6af","pId":"ce48c49","name":"01 JVM 结构","parent":"五、java 虚拟机","sort_id":1015522,"order":4,"isParent":true,"extname":null,"open":false},{"id":"83ae707","pId":0,"name":"四、数据库","parent":"","sort_id":987069,"order":4,"isParent":true,"extname":null,"open":false},{"id":"1.1.5 set 类型命令","pId":"ed9af11","name":"1.1.5 set 类型命令","parent":"四、数据库/01 redis/1.1 Redis 命令","order":4,"sort_id":995440,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"redis-集合set\" class=\"anchor\" href=\"#redis-%E9%9B%86%E5%90%88set\"\u003E\u003C/a\u003Eredis 集合(set)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 的 set 是 string 类型的无序集合。集合成员是唯一的，这就意味着集合中不能出现重复的数据。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 中集合是通过哈希表实现的，所以添加，删除，查找的复杂度都是 o(1)。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Esadd key member1 [member2]\u003C/td\u003E\n\u003Ctd\u003E向集合添加一个或多个成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Escard key\u003C/td\u003E\n\u003Ctd\u003E获取集合的成员数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Esdiff key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的差集\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Esdiffstore destination key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的差集并存储在 destination 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Esinter key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的交集\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Esinterstore destination key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的交集并存储在 destination 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Esismember key member\u003C/td\u003E\n\u003Ctd\u003E判断 member 元素是否是集合 key 的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Esmembers key\u003C/td\u003E\n\u003Ctd\u003E返回集合中的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Esmove source destination member\u003C/td\u003E\n\u003Ctd\u003E将 member 元素从 source 集合移动到 destination 集合\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Espop key\u003C/td\u003E\n\u003Ctd\u003E移除并返回集合中的一个随机元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Esrandmember key [count]\u003C/td\u003E\n\u003Ctd\u003E返回集合中一个或多个随机数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Esrem key member1 [member2]\u003C/td\u003E\n\u003Ctd\u003E移除集合中一个或多个成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Esunion key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回所有给定集合的并集\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Esunionstore destination key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E所有给定集合的并集存储在 destination 集合中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Esscan key cursor [match pattern] [count count]\u003C/td\u003E\n\u003Ctd\u003E迭代集合中的元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"1.2.3.6 删除节点","pId":"c07e325","name":"1.2.3.6 删除节点","parent":"四、数据库/01 redis/1.2 redis 高级/1.2.3 集群","order":4,"sort_id":1058134,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"参考资料\" class=\"anchor\" href=\"#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/Howinfun/article/details/81938161\"\u003ERedis集群添加和删除节点（主和从）\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-删除主节点\" class=\"anchor\" href=\"#1-%E5%88%A0%E9%99%A4%E4%B8%BB%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E1. 删除主节点\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E归还槽solt\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E这里输入代码\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1127/173516_9946fa85_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E删除从节点非常简单，删除的时候指定ip+端口以及节点id即可。\u003C/li\u003E\n\u003Cli\u003E但是删除主节点可不能直接删除，一定要先将slot槽重新移动到其他主节点那里再进行删除操作，不然存放的数据就丢失了。\u003C/li\u003E\n\u003Cli\u003E我们现在先尝试删除一个从节点（7008）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-删除子节点用del-node命令\" class=\"anchor\" href=\"#1-%E5%88%A0%E9%99%A4%E5%AD%90%E8%8A%82%E7%82%B9%E7%94%A8del-node%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 删除子节点用del-node命令。\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E此命令需要制定删除节点的ip和端口，以及节点的id\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost src]$ ./redis-trib.rb del-node 192.168.222.129:7006 5b98ed16b3ead28b072762650450b9441296ab18\n\u0026gt;\u0026gt;\u0026gt; Removing node 5b98ed16b3ead28b072762650450b9441296ab18 from cluster 192.168.222.129:7006\n\u0026gt;\u0026gt;\u0026gt; Sending CLUSTER FORGET messages to the cluster...\n\u0026gt;\u0026gt;\u0026gt; SHUTDOWN the node.\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E删除后我们再次查看集群的节点信息，如下所示，7006从节点已经被移除掉。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost redis-cluster]$ ./redis-cluster 7002\n192.168.222.129:7002\u0026gt; cluster nodes\n24ef75ce1385a29c11e1e970143670630a345711 192.168.222.129:7002@17002 myself,master - 0 1543310814000 2 connected 5461-10922\n0e2ba9c12d9c211d07530fc9242c187d175ceedb 192.168.222.129:7007@17007 master - 0 1543310815000 7 connected 10923-11922\n267be6e526fde26d544a5e041db560323f037bad 192.168.222.129:7005@17005 slave 1e61f26a3f8057264c956c4d02f6f57abf4d2d67 0 1543310814000 5 connected\n3875de68fe213d19fb8e64311031b0ebdd63e566 192.168.222.129:7004@17004 slave 24ef75ce1385a29c11e1e970143670630a345711 0 1543310815000 4 connected\nbfa68ee0d6335ebd93c8bc58f73dd67c6e67c353 192.168.222.129:7001@17001 master - 0 1543310814504 1 connected 0-5460\n287476ede647ca6eca1f2da01f1bb5efb49af4a2 192.168.222.129:7008@17008 slave 0e2ba9c12d9c211d07530fc9242c187d175ceedb 0 1543310815006 7 connected\n1e61f26a3f8057264c956c4d02f6f57abf4d2d67 192.168.222.129:7003@17003 master - 0 1543310816011 3 connected 11923-16383\n192.168.222.129:7002\u0026gt; \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E另外，我们可以发现，7008的redis服务进程也被kill掉了。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-cluster]# ps -ef | grep redis\nroot      10686      1  0 17:09 ?        00:00:01 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7008 [cluster]\nroot      16879      1  0 16:23 ?        00:00:06 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7001 [cluster]\nroot      16881      1  0 16:23 ?        00:00:05 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7002 [cluster]\nroot      16889      1  0 16:23 ?        00:00:06 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7003 [cluster]\nroot      16894      1  0 16:23 ?        00:00:05 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7004 [cluster]\nroot      16899      1  0 16:23 ?        00:00:05 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7005 [cluster] \nroot      81308      1  0 16:47 ?        00:00:04 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7007 [cluster]\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.2.4 持久化","pId":"e3fc66b","name":"1.2.4 持久化","parent":"四、数据库/01 redis/1.2 redis 高级","order":4,"sort_id":1028825,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1前言\" class=\"anchor\" href=\"#1%E5%89%8D%E8%A8%80\"\u003E\u003C/a\u003E1、前言\u003C/h3\u003E\n\u003Cp\u003ERedis是一种高级key-value数据库。它跟memcached类似，不过数据可以持久化，而且支持的数据类型很丰富。有字符串，链表，集 合和有序集合。支持在服务器端计算集合的并，交和补集(difference)等，还支持多种排序功能。所以Redis也可以被看成是一个数据结构服务 器。\nRedis的所有数据都是保存在内存中，然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”)；也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。\u003C/p\u003E\n\u003Cp\u003E由于Redis的数据都存放在内存中，如果没有配置持久化，redis重启后数据就全丢失了，于是需要开启redis的持久化功能，将数据保存到磁盘上，当redis重启后，可以从磁盘中恢复数据。redis提供两种方式进行持久化，一种是RDB持久化（原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化），另外一种是AOF（append only file）持久化（原理是将Reids的操作日志以追加的方式写入文件）。那么这两种持久化方式有什么区别呢，改如何选择呢？网上看了大多数都是介绍这两种方式怎么配置，怎么使用，就是没有介绍二者的区别，在什么应用场景下使用。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2二者的区别\" class=\"anchor\" href=\"#2%E4%BA%8C%E8%80%85%E7%9A%84%E5%8C%BA%E5%88%AB\"\u003E\u003C/a\u003E2、二者的区别\u003C/h3\u003E\n\u003Cp\u003ERDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘，实际操作过程是fork一个子进程，先将数据集写入临时文件，写入成功后，再替换之前的文件，用二进制压缩存储。\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1122/150134_65067f70_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003EAOF持久化以日志的形式记录服务器所处理的每一个写、删除操作，查询操作不会记录，以文本的方式记录，可以打开文件看到详细的操作记录。\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1122/150235_9c3cbd44_907621.png\" alt=\"\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3二者优缺点\" class=\"anchor\" href=\"#3%E4%BA%8C%E8%80%85%E4%BC%98%E7%BC%BA%E7%82%B9\"\u003E\u003C/a\u003E3、二者优缺点\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"rdb存在哪些优势呢\" class=\"anchor\" href=\"#rdb%E5%AD%98%E5%9C%A8%E5%93%AA%E4%BA%9B%E4%BC%98%E5%8A%BF%E5%91%A2\"\u003E\u003C/a\u003ERDB存在哪些优势呢？\u003C/h4\u003E\n\u003Cp\u003E1). 一旦采用该方式，那么你的整个Redis数据库将只包含一个文件，这对于文件备份而言是非常完美的。比如，你可能打算每个小时归档一次最近24小时的数据，同时还要每天归档一次最近30天的数据。通过这样的备份策略，一旦系统出现灾难性故障，我们可以非常容易的进行恢复。\u003C/p\u003E\n\u003Cp\u003E2). 对于灾难恢复而言，RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。\u003C/p\u003E\n\u003Cp\u003E3). 性能最大化。对于Redis的服务进程而言，在开始持久化时，它唯一需要做的只是fork出子进程，之后再由子进程完成这些持久化的工作，这样就可以极大的避免服务进程执行IO操作了。\u003C/p\u003E\n\u003Cp\u003E4). 相比于AOF机制，如果数据集很大，RDB的启动效率会更高。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"rdb又存在哪些劣势呢\" class=\"anchor\" href=\"#rdb%E5%8F%88%E5%AD%98%E5%9C%A8%E5%93%AA%E4%BA%9B%E5%8A%A3%E5%8A%BF%E5%91%A2\"\u003E\u003C/a\u003ERDB又存在哪些劣势呢？\u003C/h4\u003E\n\u003Cp\u003E1). 如果你想保证数据的高可用性，即最大限度的避免数据丢失，那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象，此前没有来得及写入磁盘的数据都将丢失。\u003C/p\u003E\n\u003Cp\u003E2). 由于RDB是通过fork子进程来协助完成数据持久化工作的，因此，如果当数据集较大时，可能会导致整个服务器停止服务几百毫秒，甚至是1秒钟。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"aof的优势有哪些呢\" class=\"anchor\" href=\"#aof%E7%9A%84%E4%BC%98%E5%8A%BF%E6%9C%89%E5%93%AA%E4%BA%9B%E5%91%A2\"\u003E\u003C/a\u003EAOF的优势有哪些呢？\u003C/h4\u003E\n\u003Cp\u003E1). 该机制可以带来更高的数据安全性，即数据持久性。Redis中提供了3中同步策略，即每秒同步、每修改同步和不同步。事实上，每秒同步也是异步完成的，其效率也是非常高的，所差的是一旦系统出现宕机现象，那么这一秒钟之内修改的数据将会丢失。而每修改同步，我们可以将其视为同步持久化，即每次发生的数据变化都会被立即记录到磁盘中。可以预见，这种方式在效率上是最低的。至于无同步，无需多言，我想大家都能正确的理解它。\u003C/p\u003E\n\u003Cp\u003E2). 由于该机制对日志文件的写入操作采用的是append模式，因此在写入过程中即使出现宕机现象，也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题，不用担心，在Redis下一次启动之前，我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。\u003C/p\u003E\n\u003Cp\u003E3). 如果日志过大，Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中，同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。\u003C/p\u003E\n\u003Cp\u003E4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上，我们也可以通过该文件完成数据的重建。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"aof的劣势有哪些呢\" class=\"anchor\" href=\"#aof%E7%9A%84%E5%8A%A3%E5%8A%BF%E6%9C%89%E5%93%AA%E4%BA%9B%E5%91%A2\"\u003E\u003C/a\u003EAOF的劣势有哪些呢？\u003C/h4\u003E\n\u003Cp\u003E1). 对于相同数量的数据集而言，AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。\u003C/p\u003E\n\u003Cp\u003E2). 根据同步策略的不同，AOF在运行效率上往往会慢于RDB。总之，每秒同步策略的效率是比较高的，同步禁用策略的效率和RDB一样高效。\u003C/p\u003E\n\u003Cp\u003E二者选择的标准，就是看系统是愿意牺牲一些性能，换取更高的缓存一致性（aof），还是愿意写操作频繁的时候，不启用备份来换取更高的性能，待手动运行save的时候，再做备份（rdb）。rdb这个就更有些 eventually consistent的意思了。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4常用配置\" class=\"anchor\" href=\"#4%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E4、常用配置\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"rdb持久化配置快照方式测试环境可以使用\" class=\"anchor\" href=\"#rdb%E6%8C%81%E4%B9%85%E5%8C%96%E9%85%8D%E7%BD%AE%E5%BF%AB%E7%85%A7%E6%96%B9%E5%BC%8F%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8\"\u003E\u003C/a\u003ERDB持久化配置（快照方式，测试环境可以使用）\u003C/h4\u003E\n\u003Cp\u003ERedis会将数据集的快照dump到dump.rdb文件中。此外，我们也可以通过配置文件来修改Redis服务器dump快照的频率，在打开6379.conf文件之后，我们搜索save，可以看到下面的配置信息：\u003C/p\u003E\n\u003Cp\u003Esave 900 1              #在900秒(15分钟)之后，如果至少有1个key发生变化，则dump内存快照。\u003C/p\u003E\n\u003Cp\u003Esave 300 10            #在300秒(5分钟)之后，如果至少有10个key发生变化，则dump内存快照。\u003C/p\u003E\n\u003Cp\u003Esave 60 10000        #在60秒(1分钟)之后，如果至少有10000个key发生变化，则dump内存快照。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"aof持久化配置生成环境使用建议配置为always\" class=\"anchor\" href=\"#aof%E6%8C%81%E4%B9%85%E5%8C%96%E9%85%8D%E7%BD%AE%E7%94%9F%E6%88%90%E7%8E%AF%E5%A2%83%E4%BD%BF%E7%94%A8%E5%BB%BA%E8%AE%AE%E9%85%8D%E7%BD%AE%E4%B8%BAalways\"\u003E\u003C/a\u003EAOF持久化配置（生成环境使用，建议配置为always）\u003C/h4\u003E\n\u003Cp\u003E在Redis的配置文件中存在三种同步方式，它们分别是：\u003C/p\u003E\n\u003Cp\u003Eappendfsync always     #每次有数据修改发生时都会写入AOF文件。\u003C/p\u003E\n\u003Cp\u003Eappendfsync everysec  #每秒钟同步一次，该策略为AOF的缺省策略。\u003C/p\u003E\n\u003Cp\u003Eappendfsync no          #从不同步。高效但是数据不会被持久化。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5参考资料\" class=\"anchor\" href=\"#5%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E5、参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"http://blog.csdn.net/jackpk/article/details/30073097\"\u003Ehttp://blog.csdn.net/jackpk/article/details/30073097\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.jb51.net/article/65264.htm\"\u003Ehttp://www.jb51.net/article/65264.htm\u003C/a\u003E\u003C/p\u003E"},{"id":"1.6 父子类共用变量","pId":"2fc41b2","name":"1.6 父子类共用变量","parent":"一、并发编程/01  线程基础","order":5,"sort_id":680340,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo父子类共用变量\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E7%88%B6%E5%AD%90%E7%B1%BB%E5%85%B1%E7%94%A8%E5%8F%98%E9%87%8F\"\u003E\u003C/a\u003E1. 示例demo（父子类共用变量）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class SyncDubbo2 {\n\n\tstatic class Main {\n\t\tpublic int i = 10;\n\t\tpublic synchronized void operationSup(){\n\t\t\ttry {\n\t\t\t\ti--;\n\t\t\t\tSystem.out.println(\"Main print i = \" + i);\n\t\t\t\tThread.sleep(100);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tstatic class Sub extends Main {\n\t\tpublic synchronized void operationSub(){\n\t\t\ttry {\n\t\t\t\twhile(i \u0026gt; 0) {\n\t\t\t\t\ti--;\n\t\t\t\t\tSystem.out.println(\"Sub print i = \" + i);\n\t\t\t\t\tThread.sleep(100);\t\t\n\t\t\t\t\tthis.operationSup();\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSub sub = new Sub();\n\t\t\t\tsub.operationSub();\n\t\t\t}\n\t\t});\n\t\t\n\t\tt1.start();\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.5.5 CachedThreadPool","pId":"b6b90b0","name":"2.5.5 CachedThreadPool","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":5,"sort_id":735460,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建一个可缓存线程池，应用中存在的线程数可以无限大\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic static ExecutorService newCachedThreadPool() {\n        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,\n                                      60L, TimeUnit.SECONDS,\n                                      new SynchronousQueue\u0026lt;Runnable\u0026gt;());\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E主要问题是线程数最大数是Integer.MAX_VALUE，可能会创建数量非常多的线程，甚至OOM。\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n/**\n * 测试CachedThreadPool\n */\npublic static void testCachedThreadPool() {\n    ExecutorService executorService = Executors.newCachedThreadPool();\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.execute(new TempTask(i));\n    }\n    executorService.shutdown();\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/111139_e1d60157_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"2.8.4 复杂并行","pId":"6619c4c","name":"2.8.4 复杂并行","parent":"一、并发编程/02 多线程通信/2.8 disruptor","order":5,"sort_id":822874,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0930/152203_5f7edb7c_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage bhz.fxz.seq;\n\n\nimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.YieldingWaitStrategy;\nimport com.lmax.disruptor.dsl.Disruptor;\nimport com.lmax.disruptor.dsl.ProducerType;\n\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class SeqMain {\n    /**\n     * ringbuffer 缓存大小\n     */\n    private final static int BUFFER_SIZE = 1024;\n\n    /**\n     * 线程池大小\n     */\n    private final static int THREAD_SIZE = 8;\n\n    /**\n     * 生产数量\n     */\n    private final static int LOOP = 1;\n\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n\n        long beginTime = System.currentTimeMillis();\n\n        // 0. 创建线程池\n        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_SIZE);\n\n        // 1. 创建disruptor\n        Disruptor\u0026lt;OrderEvent\u0026gt; disruptor = new Disruptor\u0026lt;OrderEvent\u0026gt;(\n                () -\u0026gt; {\n                    return new OrderEvent();\n                },\n                BUFFER_SIZE,\n                executorService,\n                ProducerType.SINGLE,\n                new YieldingWaitStrategy()\n        );\n\n        // 2. 设置消费顺序（直线顺序消费）\n        OrderHandler1 h1 = new OrderHandler1();\n        OrderHandler2 h2 = new OrderHandler2();\n        OrderHandler3 h3 = new OrderHandler3();\n        OrderHandler4 h4 = new OrderHandler4();\n        OrderHandler5 h5 = new OrderHandler5();\n        OrderHandler6 h6 = new OrderHandler6();\n\n        /**\n         *  模型\n         *\n         *          H2  --  H4\n         *       /              \\\n         *   H1                    H6\n         *       \\              /\n         *          H3  --  H5\n         */\n        disruptor.handleEventsWith(h1);\n        disruptor.after(h1).handleEventsWith(h2, h3);\n        disruptor.after(h2).handleEventsWith(h4);\n        disruptor.after(h3).handleEventsWith(h5);\n        disruptor.after(h4, h5).handleEventsWith(h6);\n\n\n        // 3. 启动\n        disruptor.start();\n\n        // 4. 生产数据\n        Future\u0026lt;?\u0026gt; future = executorService.submit(() -\u0026gt; {\n            for (int i = 0; i \u0026lt; LOOP; i++) {\n                disruptor.publishEvent((OrderEvent event, long sequence) -\u0026gt; {\n                    event.setName(\"初始化订单\");\n                    System.out.println(\"初始化订单\");\n                });\n            }\n            return null;\n        });\n\n        // 5. 保证数据生成完成\n        future.get();\n\n        // 6. 关闭资源\n        disruptor.shutdown();\n        executorService.shutdown();\n\n        System.out.println(\"耗时：\" + (System.currentTimeMillis() - beginTime));\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.5 安装git","pId":"7a86ec7","name":"1.5 安装git","parent":"三、linux /01 软件安装","order":5,"sort_id":987026,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch4\u003E\n\u003Ca id=\"1-下载git源码\" class=\"anchor\" href=\"#1-%E4%B8%8B%E8%BD%BDgit%E6%BA%90%E7%A0%81\"\u003E\u003C/a\u003E1. 下载git源码\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Ehttps://github.com/git/git/releases\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-解压\" class=\"anchor\" href=\"#2-%E8%A7%A3%E5%8E%8B\"\u003E\u003C/a\u003E2. 解压\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf git-2.17.0.tar.gz \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-编译安装\" class=\"anchor\" href=\"#3-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E3. 编译安装\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装依赖\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum -y install curl-devel expat-devel gettext-devel openssl-devel zlib zlib-devel gcc perl-ExtUtils-MakeMaker wget\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E编译\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd git-2.17.0\nsudo make prefix=/usr/local/git all\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esudo make prefix=/usr/local/git install\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4-git-基础配置\" class=\"anchor\" href=\"#4-git-%E5%9F%BA%E7%A1%80%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E4. git 基础配置\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置用户名\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global user.name \"yourname\"\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E用户名密码同步\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit clone http://username:password@127.0.0.1/res/res.git\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E列表内容\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global user.email \"youremail\"\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E忽略 win or linux 换行符转换\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global core.autocrlf false\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E编码配置\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global gui.encoding utf-8\ngit config --global core.quotepath off\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"5-ssh-for-码云\" class=\"anchor\" href=\"#5-ssh-for-%E7%A0%81%E4%BA%91\"\u003E\u003C/a\u003E5. SSH for 码云\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E生成ssh公钥\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Essh-keygen -t rsa -C \"413916057@qq.com\"  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E三次回车即可生成 ssh key\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E添加秘钥\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Essh-add ~/.ssh/xxx_rsa  #添加秘钥\n#ssh-add -d  ~/.ssh/xxx_rsa # 删除key\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E码云添加公钥\n查看你的 public key，并把他添加到码云（Gitee.com） SSH key添加地址:\u003Ca href=\"https://gitee.com/profile/sshkeys\"\u003Ehttps://gitee.com/profile/sshkeys\u003C/a\u003E)\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1204/140016_6557585d_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Essh -T git@github.com\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E设置成功，能看到：\u003C/p\u003E\n\u003Cp\u003EHi xxxxx! You've successfully authenticated, but GitHub does not provide shell access.\u003C/p\u003E"},{"id":"2.6 CentOS7中关闭firewall，并使用iptables管理防火墙","pId":"6275c3c","name":"2.6 CentOS7中关闭firewall，并使用iptables管理防火墙","parent":"三、linux /02 系统操作","order":5,"sort_id":1024065,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/xuezhigu/p/6652835.html\"\u003ECentOS7中关闭firewall，并使用iptables管理防火墙\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2关闭默认的firewall防火墙\" class=\"anchor\" href=\"#2%E5%85%B3%E9%97%AD%E9%BB%98%E8%AE%A4%E7%9A%84firewall%E9%98%B2%E7%81%AB%E5%A2%99\"\u003E\u003C/a\u003E2.关闭默认的firewall防火墙\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 关闭防火墙\nsystemctl stop firewalld.service \n\n# 关闭开机启动\nsystemctl disable firewalld.service \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-开启iptables\" class=\"anchor\" href=\"#3-%E5%BC%80%E5%90%AFiptables\"\u003E\u003C/a\u003E3. 开启iptables\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# （根据centOS7的版本和内核，有些版本已经装过，可以跳过此命令）\nyum install iptables \nyum install iptables-services\n\nservice iptables restart\n\n# 设置开机自启\nchkconfig iptables on 或者systemctl enable iptables.service \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-编辑防火墙文件开启了2122803306端口\" class=\"anchor\" href=\"#4-%E7%BC%96%E8%BE%91%E9%98%B2%E7%81%AB%E5%A2%99%E6%96%87%E4%BB%B6%E5%BC%80%E5%90%AF%E4%BA%862122803306%E7%AB%AF%E5%8F%A3\"\u003E\u003C/a\u003E4. 编辑防火墙文件（开启了21,22,80,3306端口）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/sysconfig/iptables\n \n# sampleconfiguration for iptables service \n# # you can edit thismanually or use system-config-firewall \n# # please do not askus to add additional ports/services to this default configuration \n*filter \n:INPUT ACCEPT [0:0] \n:FORWARD ACCEPT [0:0] \n:OUTPUT ACCEPT [0:0] \n-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT \n-A INPUT -p icmp -j ACCEPT \n-A INPUT -i lo -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT \n-A INPUT -j REJECT --reject-with icmp-host-prohibited \n-A FORWARD -j REJECT --reject-with icmp-host-prohibited \nCOMMIT \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-添加防火墙命令\" class=\"anchor\" href=\"#5-%E6%B7%BB%E5%8A%A0%E9%98%B2%E7%81%AB%E5%A2%99%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E5. 添加防火墙命令\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-查看本机关于iptables的设置情况\" class=\"anchor\" href=\"#6-%E6%9F%A5%E7%9C%8B%E6%9C%AC%E6%9C%BA%E5%85%B3%E4%BA%8Eiptables%E7%9A%84%E8%AE%BE%E7%BD%AE%E6%83%85%E5%86%B5\"\u003E\u003C/a\u003E6. 查看本机关于IPTABLES的设置情况\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eiptables -L -n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"ce48c49","pId":0,"name":"五、java 虚拟机","parent":"","sort_id":995800,"order":5,"isParent":true,"extname":null,"open":false},{"id":"8cf0d42","pId":"ce48c49","name":"02 垃圾回收","parent":"五、java 虚拟机","sort_id":1013228,"order":5,"isParent":true,"extname":null,"open":false},{"id":"1.1.6 zset 类型命令","pId":"ed9af11","name":"1.1.6 zset 类型命令","parent":"四、数据库/01 redis/1.1 Redis 命令","order":5,"sort_id":995533,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"redis-有序集合sorted-set\" class=\"anchor\" href=\"#redis-%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88sorted-set\"\u003E\u003C/a\u003Eredis 有序集合(sorted set)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E有序集合的成员是唯一的,但分数(score)却可以重复。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E集合是通过哈希表实现的，所以添加，删除，查找的复杂度都是o(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Ezadd key score1 member1 [score2 member2]\u003C/td\u003E\n\u003Ctd\u003E向有序集合添加一个或多个成员，或者更新已存在成员的分数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ezcard key\u003C/td\u003E\n\u003Ctd\u003E获取有序集合的成员数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Ezcount key min max\u003C/td\u003E\n\u003Ctd\u003E计算在有序集合中指定区间分数的成员数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Ezincrby key increment member\u003C/td\u003E\n\u003Ctd\u003E有序集合中对指定成员的分数加上增量 increment\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Ezinterstore destination numkeys key [key ...]\u003C/td\u003E\n\u003Ctd\u003E计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ezlexcount key min max\u003C/td\u003E\n\u003Ctd\u003E在有序集合中计算指定字典区间内成员数量\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Ezrange key start stop [withscores]\u003C/td\u003E\n\u003Ctd\u003E通过索引区间返回有序集合成指定区间内的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ezrangebylex key min max [limit offset count]\u003C/td\u003E\n\u003Ctd\u003E通过字典区间返回有序集合的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Ezrangebyscore key min max [withscores] [limit]\u003C/td\u003E\n\u003Ctd\u003E通过分数返回有序集合指定区间内的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Ezrank key member\u003C/td\u003E\n\u003Ctd\u003E返回有序集合中指定成员的索引\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Ezrem key member [member ...]\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中的一个或多个成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Ezremrangebylex key min max\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中给定的字典区间的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Ezremrangebyrank key start stop\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中给定的排名区间的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Ezremrangebyscore key min max\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中给定的分数区间的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Ezrevrange key start stop [withscores]\u003C/td\u003E\n\u003Ctd\u003E返回有序集中指定区间内的成员，通过索引，分数从高到底\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Ezrevrangebyscore key max min [withscores]\u003C/td\u003E\n\u003Ctd\u003E返回有序集中指定分数区间内的成员，分数从高到低排序\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E17\u003C/td\u003E\n\u003Ctd\u003Ezrevrank key member\u003C/td\u003E\n\u003Ctd\u003E返回有序集合中指定成员的排名，有序集成员按分数值递减(从大到小)排序\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E18\u003C/td\u003E\n\u003Ctd\u003Ezscore key member\u003C/td\u003E\n\u003Ctd\u003E返回有序集中，成员的分数值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E19\u003C/td\u003E\n\u003Ctd\u003Ezunionstore destination numkeys key [key ...]\u003C/td\u003E\n\u003Ctd\u003E计算给定的一个或多个有序集的并集，并存储在新的 key 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E20\u003C/td\u003E\n\u003Ctd\u003Ezscan key cursor [match pattern] [count count]\u003C/td\u003E\n\u003Ctd\u003E迭代有序集合中的元素（包括元素成员和元素分值）\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"1.7 异常处理","pId":"2fc41b2","name":"1.7 异常处理","parent":"一、并发编程/01  线程基础","order":6,"sort_id":680382,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo异常处理\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86\"\u003E\u003C/a\u003E1. 示例demo（异常处理）\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E不跳出循环\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class SyncException {\n\n\tprivate int i = 0;\n\tpublic synchronized void operation(){\n\t\twhile(true){\n\t\t\ttry {\n\t\t\t\ti++;\n\t\t\t\tThread.sleep(100);\n\t\t\t\tSystem.out.println(Thread.currentThread().getName() + \" , i = \" + i);\n\t\t\t\tif(i == 20){\n\t\t\t\t\tInteger.parseInt(\"a\");\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal SyncException se = new SyncException();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tse.operation();\n\t\t\t}\n\t\t},\"t1\");\n\t\tt1.start();\n\t}\n\t\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E跳出循环，可以抛出异常\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class SyncException {\n\n\tprivate int i = 0;\n\tpublic synchronized void operation(){\n\t\twhile(true){\n\t\t\ttry {\n\t\t\t\ti++;\n\t\t\t\tThread.sleep(100);\n\t\t\t\tSystem.out.println(Thread.currentThread().getName() + \" , i = \" + i);\n\t\t\t\tif(i == 20){\n\t\t\t\t\t//Integer.parseInt(\"a\");\n\t\t\t\t\tthrow new RuntimeException();\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal SyncException se = new SyncException();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tse.operation();\n\t\t\t}\n\t\t},\"t1\");\n\t\tt1.start();\n\t}\n\t\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"2.5.6 ScheduledThreadPool","pId":"b6b90b0","name":"2.5.6 ScheduledThreadPool","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":6,"sort_id":735480,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建一个定长线程池，支持定时及周期性任务执行。延迟执行示例代码如下：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic ScheduledThreadPoolExecutor(int corePoolSize) {\n        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,\n              new DelayedWorkQueue());\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E主要问题是线程数最大数是Integer.MAX_VALUE，可能会创建数量非常多的线程，甚至OOM。\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n/**\n * 测试ScheduledThreadPool\n */\npublic static void testScheduledThreadPool() {\n    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);\n    System.out.println(\"准备开始时间：\" + format.format(new Date()));\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.schedule(new TempTask(i)  , 3 , TimeUnit.SECONDS);\n    }\n    executorService.shutdown();\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/112105_9aee4d78_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E"},{"id":"3b56f09","pId":"77fbb9c","name":"2.6 concurrent工具类","parent":"一、并发编程/02 多线程通信","sort_id":736282,"order":6,"isParent":true,"extname":null,"open":false},{"id":"1.6 安装Maven","pId":"7a86ec7","name":"1.6 安装Maven","parent":"三、linux /01 软件安装","order":6,"sort_id":987027,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1下载安装文件\" class=\"anchor\" href=\"#1%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E1.下载安装文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz解压安装：\n\ntar -zxvf apache-maven-3.3.9-bin.tar.gz\n\nmv apache-maven-3.3.9 maven (这一步骤可省略，主要是为了后面方便操作)配置环境变量\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-使用vim编辑etcprofile文件\" class=\"anchor\" href=\"#2-%E4%BD%BF%E7%94%A8vim%E7%BC%96%E8%BE%91etcprofile%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E2. 使用vim编辑/etc/profile文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E在/etc/profile文件末尾增加以下配置：     \nM2_HOME=/opt/tyrone/maven （注意这里是maven的安装路径）\nexport PATH=${M2_HOME}/bin:${PATH}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-重载etcprofile这个文件\" class=\"anchor\" href=\"#3-%E9%87%8D%E8%BD%BDetcprofile%E8%BF%99%E4%B8%AA%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E3. 重载/etc/profile这个文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esource /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-检验maven是否安装成功\" class=\"anchor\" href=\"#4-%E6%A3%80%E9%AA%8Cmaven%E6%98%AF%E5%90%A6%E5%AE%89%E8%A3%85%E6%88%90%E5%8A%9F\"\u003E\u003C/a\u003E4. 检验maven是否安装成功\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Emvn -v\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/094826_66db254c_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-创建仓库目录\" class=\"anchor\" href=\"#5-%E5%88%9B%E5%BB%BA%E4%BB%93%E5%BA%93%E7%9B%AE%E5%BD%95\"\u003E\u003C/a\u003E5. 创建仓库目录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost repository]$ cd /usr/local/deve/soft/maven-3.5.3/\n[fxz@localhost maven-3.5.3]$ mkdir repository\n[fxz@localhost maven-3.5.3]$ cd repository/\n[fxz@localhost repository]$ pwd\n/usr/local/deve/soft/maven-3.5.3/repository\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-修改settingxml\" class=\"anchor\" href=\"#6-%E4%BF%AE%E6%94%B9settingxml\"\u003E\u003C/a\u003E6. 修改setting.xml\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 配置仓库地址\n\u0026lt;localRepository\u0026gt;/usr/local/deve/soft/maven-3.5.3/repository\u0026lt;/localRepository\u0026gt;\n\n# 配置私仓地址\n\u0026lt;mirror\u0026gt;\n        \u0026lt;id\u0026gt;nexus-aliyun\u0026lt;/id\u0026gt;\n        \u0026lt;mirrorOf\u0026gt;*\u0026lt;/mirrorOf\u0026gt;\n        \u0026lt;name\u0026gt;Nexus aliyun\u0026lt;/name\u0026gt;\n        \u0026lt;url\u0026gt;http://maven.aliyun.com/nexus/content/groups/public\u0026lt;/url\u0026gt;\n    \u0026lt;/mirror\u0026gt;\n\n     \u0026lt;mirror\u0026gt;\n        \u0026lt;id\u0026gt;nexus-osc\u0026lt;/id\u0026gt;\n        \u0026lt;mirrorOf\u0026gt;central\u0026lt;/mirrorOf\u0026gt;\n        \u0026lt;name\u0026gt;Nexus osc\u0026lt;/name\u0026gt;\n        \u0026lt;url\u0026gt;http://192.168.1.250:8081/nexus/content/groups/public\u0026lt;/url\u0026gt;\n    \u0026lt;/mirror\u0026gt;\n    \u0026lt;mirror\u0026gt;\n        \u0026lt;id\u0026gt;nexus-osc-thirdparty\u0026lt;/id\u0026gt;\n        \u0026lt;mirrorOf\u0026gt;thirdparty\u0026lt;/mirrorOf\u0026gt;\n        \u0026lt;name\u0026gt;Nexus osc thirdparty\u0026lt;/name\u0026gt;\n        \u0026lt;url\u0026gt;http://192.168.1.250:8081/nexus/content/repositories/thirdparty/\u0026lt;/url\u0026gt;\n    \u0026lt;/mirror\u0026gt;\n\n# 配置profile\n\n \u0026lt;id\u0026gt;jdk-1.8\u0026lt;/id\u0026gt;\n         \u0026lt;activation\u0026gt;\n             \u0026lt;activeByDefault\u0026gt;true\u0026lt;/activeByDefault\u0026gt;\n             \u0026lt;jdk\u0026gt;1.8\u0026lt;/jdk\u0026gt;\n          \u0026lt;/activation\u0026gt;\n          \u0026lt;properties\u0026gt;\n              \u0026lt;maven.compiler.source\u0026gt;1.8\u0026lt;/maven.compiler.source\u0026gt;\n              \u0026lt;maven.compiler.target\u0026gt;1.8\u0026lt;/maven.compiler.target\u0026gt;\n              \u0026lt;maven.compiler.compilerVersion\u0026gt;1.8\u0026lt;/maven.compiler.compilerVersion\u0026gt;\n          \u0026lt;/properties\u0026gt;\n\n      \u0026lt;repositories\u0026gt;\n        \u0026lt;repository\u0026gt;\n          \u0026lt;id\u0026gt;nexus\u0026lt;/id\u0026gt;\n          \u0026lt;name\u0026gt;OSChina Central\u0026lt;/name\u0026gt;\n          \u0026lt;url\u0026gt;http://192.168.1.250:8081/nexus/content/groups/public\u0026lt;/url\u0026gt;\n        \u0026lt;/repository\u0026gt;\n\n        \u0026lt;repository\u0026gt;\n            \u0026lt;id\u0026gt;sonatype-nexus-snapshots\u0026lt;/id\u0026gt;\n            \u0026lt;url\u0026gt;https://oss.sonatype.org/content/repositories/snapshots\u0026lt;/url\u0026gt;\n            \u0026lt;releases\u0026gt;\n                \u0026lt;enabled\u0026gt;false\u0026lt;/enabled\u0026gt;\n            \u0026lt;/releases\u0026gt;\n            \u0026lt;snapshots\u0026gt;\n                \u0026lt;enabled\u0026gt;true\u0026lt;/enabled\u0026gt;\n            \u0026lt;/snapshots\u0026gt;\n        \u0026lt;/repository\u0026gt;\n      \u0026lt;/repositories\u0026gt;\n\n\u0026lt;pluginRepositories\u0026gt;\n        \u0026lt;pluginRepository\u0026gt;\n          \u0026lt;id\u0026gt;nexus2\u0026lt;/id\u0026gt;\n          \u0026lt;name\u0026gt;local private nexus\u0026lt;/name\u0026gt;\n          \u0026lt;url\u0026gt; http://192.168.1.250:8081/nexus/content/groups/public \u0026lt;/url\u0026gt;\n        \u0026lt;/pluginRepository\u0026gt;\n      \u0026lt;/pluginRepositories\u0026gt;\n\n\n\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"4f9a92e","pId":0,"name":"六、中间件","parent":"","sort_id":1060676,"order":6,"isParent":true,"extname":null,"open":false},{"id":"1.1.7 java 操作redis","pId":"ed9af11","name":"1.1.7 java 操作redis","parent":"四、数据库/01 redis/1.1 Redis 命令","order":6,"sort_id":995289,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Cpre\u003E\u003Ccode\u003Epackage com.i84.insect.core.config.redis;\n\nimport com.xiaoleilu.hutool.date.DateUtil;\nimport org.apache.log4j.Logger;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.connection.RedisConnection;\nimport org.springframework.data.redis.core.RedisCallback;\nimport org.springframework.data.redis.core.RedisTemplate;\n\nimport java.util.*;\n\n/**\n * 类描述    : redis操作类，用于缓存 \u0026lt;br/\u0026gt;\n * 项目名称  : xlauch 项目\u0026lt;br/\u0026gt;\n * 类名称    : RedisManager \u0026lt;br/\u0026gt;\n *\n * @author 伊凡  413916057@qq.com\u0026lt;br/\u0026gt;\n *         创建日期: 2017/11/8 14:54  \u0026lt;br/\u0026gt;\n * @version 0.1\n */\n@Configuration\npublic class RedisManager {\n\n    private static final Logger log = Logger.getLogger(RedisManager.class);\n\n    @Autowired\n    private RedisTemplate\u0026lt;String, String\u0026gt; redisTemplate;\n\n    /**\n     * 生成id专用\n     */\n    public static final String ID = \"id\";\n\n    /********************************** 类型：键 *********************************/\n    /**\n     * 类型：键\n     * 删除给定的一个 key\n     * @param key\n     * @return\n     */\n    public void del(final String key) {\n        redisTemplate.delete(key);\n    }\n\n    /**\n     * 类型：键\n     * 批量删除键值\n     * @param prestr\n     * @return\n     */\n    public void batchDel(final String prestr){\n        Set\u0026lt;String\u0026gt; set = keys(prestr +\"*\");\n        redisTemplate.delete(set);\n    }\n\n    /**\n     * 类型：键\n     * 查找所有符合给定模式 pattern 的 key\n     * KEYS * 匹配数据库中所有 key\n     * @param pattern\n     * @return\n     */\n    public Set\u0026lt;String\u0026gt; keys(final String pattern) {\n        return redisTemplate.keys(pattern);\n    }\n\n    /**\n     * 类型：键\n     * 检查给定 key 是否存在\n     * @param key\n     * @return\n     */\n    public Boolean exists(final String key) {\n        return redisTemplate.execute(new RedisCallback\u0026lt;Boolean\u0026gt;() {\n            @Override\n            public Boolean doInRedis(RedisConnection redisConnection) {\n                return redisConnection.exists(key.getBytes());\n            }\n        });\n    }\n\n\n    /********************************** 类型：字符串 *********************************/\n\n    /**\n     * 类型：字符串\n     * 将字符串值 value 关联到 key\n     * 如果 key 已经持有其他值， SET 就覆写旧值，无视类型\n     * @param key\n     * @param value\n     */\n    public void set(final String key, final String value) {\n        redisTemplate.opsForValue().set(key, value);\n    }\n\n    /**\n     * 如果 key 已经存在并且是一个字符串， APPEND 命令将 value 追加到 key 原来的值的末尾。\n     * 如果 key 不存在， APPEND 就简单地将给定 key 设为 value ，就像执行 SET key value 一样。\n     *\n     * @param key the key\n     * @param appendValue the append value\n     */\n    public void append(final String key, final String appendValue) {\n        redisTemplate.opsForValue().append(key, appendValue);\n    }\n\n    /**\n     *  类型：字符串\n     *  将字符串值 value 关联到 key 并设置失效时间\n     * @param key\n     * @param value\n     * @param expireTime\n     */\n    public void setWithExp(final String key, final String value, final Date expireTime) {\n        redisTemplate.opsForValue().set(key, value);\n        redisTemplate.expireAt(key, expireTime);\n    }\n\n    /**\n     * 类型：字符串\n     * 返回 key 所关联的字符串值\n     * @param key\n     * @return\n     */\n    public String get(final String key) {\n        return redisTemplate.opsForValue().get(key);\n    }\n\n    /**\n     * 类型：字符串\n     * 创建数据id，所有额都通过此方法创建\n     *\n     * @return\n     */\n    public long createID() {\n        return redisTemplate.opsForValue().increment(ID, 1);\n    }\n\n    /**\n     * 类型：字符串\n     * 创建相应模块的自增长id\n     * @author\n     * Jun 23, 2014 11:46:00 AM\n     */\n    public long createModuleID(final String module){\n        Long value = redisTemplate.opsForValue().increment(module, 1);\n        redisTemplate.expireAt(module, DateUtil.offsetMinute(new Date(), 1));\n        return value;\n    }\n\n    /**\n     * 类型：字符串\n     * 用于统计当天的短信数\n     * key smscnt:当前日期:手机号 如：smscnt:20160115:12345678901\n     * unixTime 当天23:59:59的unix时间戳\n     * @author\n     * Jun 23, 2014 11:46:00 AM\n     */\n    public long incrWithExpire(final String key, final Date date){\n        Long value = redisTemplate.opsForValue().increment(key, 1);\n        redisTemplate.expireAt(key, date);\n        return value;\n    }\n\n    /**\n     * 类型：字符串\n     * +value的和\n     * @param key\n     * @param value\n     * @return\n     */\n    public long incrBy(final String key, final long value) {\n        Long value1 = redisTemplate.opsForValue().increment(key, value);\n        return value1;\n    }\n\n    /********************************** 类型：hash *********************************/\n    /**\n     * 类型：hash\n     * 将哈希表 key 中的域 field 的值设为 value\n     * @param key\n     * @param field\n     * @param value\n     */\n    public void hset(final String key, final String field, final String value) {\n        redisTemplate.opsForHash().put(key, field, value);\n    }\n\n    /**\n     * 类型：hash\n     * 返回哈希表 key 中给定域 field 的值\n     * @param key\n     * @param field\n     * @return\n     */\n    public String hget(final String key, final String field) {\n        if (redisTemplate.opsForHash().get(key, field) != null) {\n            return redisTemplate.opsForHash().get(key, field)+\"\";\n        }\n        return null ;\n    }\n\n    /**\n     * 类型：hash\n     * 返回哈希表 key 中，所有的域和值\n     * @param key\n     * @return\n     */\n    public Map\u0026lt;Object, Object\u0026gt; hgetAll(final String key) {\n        return redisTemplate.opsForHash().entries(key);\n    }\n\n    /**\n     * 类型：hash\n     * 查看哈希表 key 中，给定域 field 是否存在\n     * @param key\n     * @param field\n     * @return\n     */\n    public Boolean hexists(final String key, final String field) {\n        return redisTemplate.opsForHash().hasKey(key, field);\n    }\n\n    /**\n     * 类型：hash\n     * 返回哈希表 key 中域的数量\n     * @param key\n     * @return\n     */\n    public Long hlen(final String key){\n        return redisTemplate.opsForHash().size(key);\n    }\n\n    /**\n     * 类型：hash\n     * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long hdel(final String key, final String... members) {\n        return redisTemplate.opsForHash().delete(key, members);\n    }\n\n    /**\n     * 类型：hash\n     * 同时将多个 field-value (域-值)对设置到哈希表 key 中\n     * @param key\n     * @param map\n     */\n    public void hmset(final String key, final Map\u0026lt;String, String\u0026gt; map) {\n        if (map == null || map.size() == 0) {\n            return;\n        }\n        redisTemplate.opsForHash().putAll(key, map);\n    }\n\n    /**\n     * 类型：hash\n     * 为哈希表 key 中的域 field 的值加上增量 increment 。\n     * 增量也可以为负数，相当于对给定域进行减法操作。\n     * 如果 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。\n     * 如果域 field 不存在，那么在执行命令前，域的值被初始化为 0 。\n     * 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。\n     * 本操作的值被限制在 64 位(bit)有符号数字表示之内。\n     *\n     * @param key the key\n     * @param field the field\n     * @param value the value\n     */\n    public Long hincrby(final String key, final String field, final long value) {\n        return redisTemplate.opsForHash().increment(key, field, value);\n    }\n\n    /********************************** 类型：set *********************************/\n    /**\n     * 类型：set\n     * 如果命令执行时，只提供了 key 参数，那么返回集合中的一个随机元素\n     * @param key\n     * @return\n     */\n    public String srandmember(final String key) {\n        return redisTemplate.execute(new RedisCallback\u0026lt;String\u0026gt;() {\n\n            @Override\n            public String doInRedis(RedisConnection redisConnection) {\n                return new String(redisConnection.sRandMember(key.getBytes()));\n            }\n        });\n    }\n\n    /**\n     * 类型：set\n     * 返回集合 key 中的所有成员\n     * @param key\n     * @return\n     */\n    public Set\u0026lt;byte[]\u0026gt; smembers(final String key) {\n        return redisTemplate.execute(new RedisCallback\u0026lt;Set\u0026lt;byte[]\u0026gt;\u0026gt;() {\n\n            @Override\n            public Set\u0026lt;byte[]\u0026gt; doInRedis(RedisConnection redisConnection) {\n                return redisConnection.sMembers(key.getBytes());\n            }\n        });\n    }\n\n    /**\n     * 类型：set\n     * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long sadd(final String key, final String... members) {\n        return redisTemplate.opsForSet().add(key, members);\n    }\n\n    /**\n     * 类型：set\n     * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long srem(final String key, final String... members) {\n        return redisTemplate.opsForSet().remove(key, members);\n    }\n\n    /**\n     * 类型：set\n     * 判断 member 元素是否集合 key 的成员\n     * @param key\n     * @param value\n     * @return\n     */\n    public Boolean sismember(final String key, final String value) {\n        return redisTemplate.opsForSet().isMember(key, value);\n    }\n\n    /**\n     * 类型：set\n     * 返回两个集合的全部成员，该集合是所有给定集合的交集。\n     * @param key1\n     * @param key2\n     * @return\n     */\n    public Set\u0026lt;String\u0026gt; sinter(final String key1, final String key2){\n        return redisTemplate.opsForSet().intersect(key1, key2);\n    }\n\n    /********************************** 类型：list *********************************/\n    /**\n     * 类型：list\n     * 返回列表 key 中指定区间内的元素，区间以偏移量 startIndex 和 endIndex 指定\n     * @param key\n     * @param startIndex\n     * @param endIndex\n     * @return\n     */\n    public List\u0026lt;String\u0026gt; lrange(final String key, final long startIndex, final long endIndex) {\n        return redisTemplate.opsForList().range(key, startIndex, endIndex);\n    }\n\n    /**\n     * 类型：list\n     * 返回列表 key所有元素\n     * @param key\n     * @return\n     */\n    public List\u0026lt;String\u0026gt; lrange(final String key) {\n        return redisTemplate.opsForList().range(key, 0, -1);\n    }\n\n    /**\n     * 类型：list\n     * 从头部删除一个元素,\n     * @param key\n     * @return\n     */\n    public String lpop(final String key) {\n        return redisTemplate.opsForList().leftPop(key);\n    }\n\n    /**\n     * 类型：list\n     * 将列表 key 下标为 index 的元素的值设置为 value\n     * @param key\n     * @param index\n     * @param value\n     * @return\n     */\n    public Boolean lset(final String key, final int index, final String value) {\n        redisTemplate.opsForList().set(key, index, value);\n        return true;\n    }\n\n    /**\n     * 类型：list\n     * 移除并返回列表 key 的尾元素\n     * @param key the key\n     * @return the string\n     */\n    public String rpop(final String key) {\n        return redisTemplate.opsForList().rightPop(key);\n    }\n\n    /**\n     * 类型：list\n     * 根据参数 count 的值，移除列表中与参数 value 相等的元素\n     * count \u0026gt; 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count\n     * count \u0026lt; 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值\n     * count = 0 : 移除表中所有与 value 相等的值\n     * @param key the key\n     * @param count the count\n     * @param value the value\n     * @return the long\n     */\n    public long lrem(final String key, final long count, final String value) {\n        return redisTemplate.opsForList().remove(key, count, value);\n    }\n\n    /**\n     * 类型：list\n     * 将一个或多个值 value 插入到列表 key 的表尾(最右边)\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long rpush(final String key, final String... members) {\n        return redisTemplate.opsForList().rightPushAll(key, members);\n    }\n\n    /**\n     * 类型：list\n     * 返回列表 key 的长度\n     * @param key\n     * @return\n     */\n    public Long llen(final String key) {\n        return redisTemplate.opsForList().size(key);\n    }\n\n\n    /**\n     * 类型 ：list\n     * 将一个或多个值 value 插入到列表 key 的表头\n     *\n     * @param key the key\n     * @param values the values\n     * @return the size after push\n     */\n    public Long lpush(final String key, final String... values) {\n        return redisTemplate.opsForList().leftPushAll(key, values);\n    }\n\n    /********************************** 类型：server *********************************/\n    /**\n     * 类型：server\n     * 返回当前数据库的 key 的数量。\n     * @return\n     */\n    public long dbsize() {\n        return redisTemplate.execute(new RedisCallback\u0026lt;Long\u0026gt;() {\n\n            @Override\n            public Long doInRedis(RedisConnection redisConnection) {\n                return redisConnection.dbSize();\n            }\n        });\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.8 变更锁","pId":"2fc41b2","name":"1.8 变更锁","parent":"一、并发编程/01  线程基础","order":7,"sort_id":684142,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo-字符对象变更锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo-%E5%AD%97%E7%AC%A6%E5%AF%B9%E8%B1%A1%E5%8F%98%E6%9B%B4%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo 字符对象变更锁\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ChangeLock {\n\n\tprivate String lock = \"lock\";\n\t\n\tprivate void method(){\n\t\tsynchronized (lock) {\n\t\t\ttry {\n\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"开始\");\n\t\t\t\tlock = \"change lock\";\n\t\t\t\tThread.sleep(2000);\n\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"结束\");\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\n\t\tfinal ChangeLock changeLock = new ChangeLock();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tchangeLock.method();\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tchangeLock.method();\n\t\t\t}\n\t\t},\"t2\");\n\t\tt1.start();\n\t\ttry {\n\t\t\tThread.sleep(100);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\tt2.start();\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1线程先持有字符对象的Lock锁，并修改字符对象内容，导致lock发生变更，t2线程就无需等待t1执行，直接获得变更后的新锁\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例demo-bean对象变更锁\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8Bdemo-bean%E5%AF%B9%E8%B1%A1%E5%8F%98%E6%9B%B4%E9%94%81\"\u003E\u003C/a\u003E2. 示例demo bean对象变更锁\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ModifyLock {\n\t\n\tprivate String name ;\n\tprivate int age ;\n\t\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\tpublic int getAge() {\n\t\treturn age;\n\t}\n\tpublic void setAge(int age) {\n\t\tthis.age = age;\n\t}\n\t\n\tpublic synchronized void changeAttributte(String name, int age) {\n\t\ttry {\n\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 开始\");\n\t\t\tthis.setName(name);\n\t\t\tthis.setAge(age);\n\t\t\t\n\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 修改对象内容为： \" \n\t\t\t\t\t+ this.getName() + \", \" + this.getAge());\n\t\t\t\n\t\t\tThread.sleep(2000);\n\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 结束\");\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal ModifyLock modifyLock = new ModifyLock();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmodifyLock.changeAttributte(\"张三\", 20);\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmodifyLock.changeAttributte(\"李四\", 21);\n\t\t\t}\n\t\t},\"t2\");\n\t\t\n\t\tt1.start();\n\t\ttry {\n\t\t\tThread.sleep(100);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\tt2.start();\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0823/092107_d7c91f85_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E虽然t1在获得\"modifyLock\"对象lock后，对其属性值进行修改，但是同一对象属性的修改不会影响锁的情况\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.5.7 自定义线程池","pId":"b6b90b0","name":"2.5.7 自定义线程池","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":7,"sort_id":736023,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.height.fxz;\n\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/7\n */\npublic class SelfThreadPoolTest {\n\n    private static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    /**\n     * 测试线程类\n     */\n    static class TempTask implements Runnable {\n\n        private int taskId;\n\n        public TempTask(int taskId) {\n            this.taskId = taskId;\n        }\n\n        @Override\n        public void run() {\n            System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    /**\n     * 在使用有界队列时，若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，\n     * 若大于corePoolSize，则会将任务加入队列，\n     * 若队列已满，则在总线程数不大于maximumPoolSize的前提下，创建新的线程，\n     * 若线程数大于maximumPoolSize，则执行拒绝策略。或其他自定义方式。\n     */\n    public static void testArrayBlockQueueThreadPool() {\n        ExecutorService executorService = new ThreadPoolExecutor(\n                1, 2,\n                60, TimeUnit.SECONDS,\n                new ArrayBlockingQueue\u0026lt;Runnable\u0026gt;(3),\n//                new LinkedBlockingDeque\u0026lt;\u0026gt;(),\n                new RejectedExecutionHandler() {\n                    @Override\n                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {\n                        TempTask tempTask = (TempTask) r;\n                        System.out.println(\"线程\" + tempTask.taskId + \" 被拒绝了\");\n                    }\n                });\n\n\n        for (int i = 0; i \u0026lt; 6; i++) {\n            executorService.execute(new TempTask(i));\n        }\n\n        executorService.shutdown();\n    }\n\n    public static void main(String[] args) {\n        testArrayBlockQueueThreadPool();\n    }\n\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-使用有界队列\" class=\"anchor\" href=\"#2-%E4%BD%BF%E7%94%A8%E6%9C%89%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E2. 使用有界队列\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/151219_381ea909_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在使用有界队列时，若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，\u003C/li\u003E\n\u003Cli\u003E若大于corePoolSize，则会将任务加入队列，\u003C/li\u003E\n\u003Cli\u003E若队列已满，则在总线程数不大于maximumPoolSize的前提下，创建新的线程，\u003C/li\u003E\n\u003Cli\u003E若线程数大于maximumPoolSize，则执行拒绝策略。或其他自定义方式。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-使用无界队列\" class=\"anchor\" href=\"#3-%E4%BD%BF%E7%94%A8%E6%97%A0%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E3. 使用无界队列\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/151251_726c0312_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在使用有界队列时，若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，\u003C/li\u003E\n\u003Cli\u003E若大于corePoolSize，则会将任务加入队列，\u003C/li\u003E\n\u003Cli\u003E无界队列会快速增长，直到耗尽系统内存\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"5fc2e0f","pId":"77fbb9c","name":"2.7 Lock 锁","parent":"一、并发编程/02 多线程通信","sort_id":798365,"order":7,"isParent":true,"extname":null,"open":false},{"id":"3119987","pId":0,"name":"七、容器、集成","parent":"","sort_id":1094074,"order":7,"isParent":true,"extname":null,"open":false},{"id":"1.7 安装Svn","pId":"7a86ec7","name":"1.7 安装Svn","parent":"三、linux /01 软件安装","order":7,"sort_id":987028,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考链接\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5\"\u003E\u003C/a\u003E1. 参考链接\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/test1280/article/details/70859797\"\u003ELinux：Subversion客户端安装及配置\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://subversion.apache.org/packages.html\"\u003ESVN 官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-yum-方式安装\" class=\"anchor\" href=\"#2-yum-%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. yum 方式安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装命令\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install subversion\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/103525_2b8f31cc_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/103618_15248ec3_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/103912_51cc5e7f_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E查看安装路径\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost tar]# which svn\n/usr/bin/svn\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-安装服务端\" class=\"anchor\" href=\"#3-%E5%AE%89%E8%A3%85%E6%9C%8D%E5%8A%A1%E7%AB%AF\"\u003E\u003C/a\u003E3. 安装服务端\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install mod_dav_svn\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.1.8 其它命令","pId":"ed9af11","name":"1.1.8 其它命令","parent":"四、数据库/01 redis/1.1 Redis 命令","order":7,"sort_id":1018780,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Edel key\u003C/td\u003E\n\u003Ctd\u003E该命令用于在 key 存在时删除 key。\u003C/td\u003E\n\u003Ctd\u003Edel w3ckey\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Edump key\u003C/td\u003E\n\u003Ctd\u003E序列化给定 key ，并返回被序列化的值。\u003C/td\u003E\n\u003Ctd\u003EDUMP greeting\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Eexists key\u003C/td\u003E\n\u003Ctd\u003E检查给定 key 是否存在。\u003C/td\u003E\n\u003Ctd\u003Eexists key\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Eexpire key seconds\u003C/td\u003E\n\u003Ctd\u003E为给定 key 设置过期时间，以秒计。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Eexpireat key timestamp\u003C/td\u003E\n\u003Ctd\u003E为 key 设置过期时间。接受的时间参数是 UNIX 时间戳(unix timestamp)\u003C/td\u003E\n\u003Ctd\u003EEXPIREAT runoobkey 1293840000\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Epexpire key milliseconds\u003C/td\u003E\n\u003Ctd\u003E设置 key 的过期时间以毫秒计。\u003C/td\u003E\n\u003Ctd\u003EPEXPIRE mykey 1500\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Epexpireat key milliseconds-timestamp\u003C/td\u003E\n\u003Ctd\u003E设置 key 过期时间的时间戳(unix timestamp) 以毫秒计\u003C/td\u003E\n\u003Ctd\u003EPEXPIREAT runoobkey 1555555555005\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ekeys pattern\u003C/td\u003E\n\u003Ctd\u003E查找所有符合给定模式( pattern)的 key 。\u003C/td\u003E\n\u003Ctd\u003EKEYS runoob*\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Emove key db\u003C/td\u003E\n\u003Ctd\u003E将当前数据库的 key 移动到给定的数据库 db 当中。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Epersist key\u003C/td\u003E\n\u003Ctd\u003E移除 key 的过期时间，key 将持久保持。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Epttl key\u003C/td\u003E\n\u003Ctd\u003E以毫秒为单位返回 key 的剩余的过期时间。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Ettl key\u003C/td\u003E\n\u003Ctd\u003E以秒为单位，返回给定 key 的剩余生存时间(ttl, time to live)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Erandomkey\u003C/td\u003E\n\u003Ctd\u003E从当前数据库中随机返回一个 key 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Erename key newkey\u003C/td\u003E\n\u003Ctd\u003E修改 key 的名称\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Erenamenx key newkey\u003C/td\u003E\n\u003Ctd\u003E仅当 newkey 不存在时，将 key 改名为 newkey 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Etype key\u003C/td\u003E\n\u003Ctd\u003E返回 key 所储存的值的类型。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"},{"id":"1.9 死锁（常量锁）","pId":"2fc41b2","name":"1.9 死锁（常量锁）","parent":"一、并发编程/01  线程基础","order":8,"sort_id":680440,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo-常量锁死锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo-%E5%B8%B8%E9%87%8F%E9%94%81%E6%AD%BB%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo 常量锁（死锁）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class StringLock {\n\n\tpublic void method() {\n\t\t//new String(\"字符串常量\")\n\t\tsynchronized (\"字符串常量\") {\n\t\t\ttry {\n\t\t\t\twhile(true){\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"开始\");\n\t\t\t\t\tThread.sleep(1000);\t\t\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"结束\");\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal StringLock stringLock = new StringLock();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tstringLock.method();\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tstringLock.method();\n\t\t\t}\n\t\t},\"t2\");\n\t\t\n\t\tt1.start();\n\t\tt2.start();\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用常量锁，常量永远只是一个对象，当第一个线程获取锁后，如果不释放，其它线程永远获取不到锁\u003C/li\u003E\n\u003Cli\u003E可以使用new String(\"字符串常量\") 代替\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"2.5.8  线程池拒绝策略","pId":"b6b90b0","name":"2.5.8  线程池拒绝策略","parent":"一、并发编程/02 多线程通信/2.5 线程池","order":8,"sort_id":736129,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-jdk内置了四种拒绝策略\" class=\"anchor\" href=\"#1-jdk%E5%86%85%E7%BD%AE%E4%BA%86%E5%9B%9B%E7%A7%8D%E6%8B%92%E7%BB%9D%E7%AD%96%E7%95%A5\"\u003E\u003C/a\u003E1. JDK内置了四种拒绝策略：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EAbortPolicy策略\n该策略直接抛出异常，阻止系统工作\u003C/li\u003E\n\u003Cli\u003ECallerRunsPolicy策略\n只要线程池未关闭，该策略直接在调用者线程中运行当前被丢弃的任务。显然这样不会真的丢弃任务，但是，调用者线程性能可能急剧下降。\u003C/li\u003E\n\u003Cli\u003EDiscardOledestPolicy策略\n丢弃最老的一个请求任务，也就是丢弃一个即将被执行的任务，并尝试再次提交当前任务。\u003C/li\u003E\n\u003Cli\u003EDiscardPolicy策略\n默默的丢弃无法处理的任务，不予任何处理。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-实现rejectedexecutiohandler接口自定义拒绝策略\" class=\"anchor\" href=\"#2-%E5%AE%9E%E7%8E%B0rejectedexecutiohandler%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8B%92%E7%BB%9D%E7%AD%96%E7%95%A5\"\u003E\u003C/a\u003E2. 实现RejectedExecutioHandler接口，自定义拒绝策略\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic interfaceRejectedExecutionHandler{\n    void rejectedExecution(Runnable r,ThreadPoolExecutor executor);\n}\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"6619c4c","pId":"77fbb9c","name":"2.8 disruptor","parent":"一、并发编程/02 多线程通信","sort_id":820040,"order":8,"isParent":true,"extname":null,"open":false},{"id":"1.8  安装frp","pId":"7a86ec7","name":"1.8  安装frp","parent":"三、linux /01 软件安装","order":8,"sort_id":987029,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch4\u003E\n\u003Ca id=\"1-下载frp\" class=\"anchor\" href=\"#1-%E4%B8%8B%E8%BD%BDfrp\"\u003E\u003C/a\u003E1. 下载frp\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/fatedier/frp/blob/master/README_zh.md\"\u003Egit 地址\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/fatedier/frp/releases\"\u003E安装包下载\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E1.1 解压tar\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf frp_0.17.0_linux_amd64.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1.2 配置frps服务端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[common]\nbind_port = 7000\nvhost_http_port = 9080\nvhost_https_port = 443\n\n\ndashboard_port = 7500\n# dashboard 用户名密码，默认都为 admin\ndashboard_user = admin\ndashboard_pwd = admin\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1.3 配置frpc客户端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[common]\nserver_addr = 39.106.64.79\nserver_port = 7000\n\n[web]\ntype = http\nlocal_port = 8080\ncustom_domains = xcx.xlauch.com\n\n[web01]\ntype = https\nlocal_port = 443\ncustom_domains = xcx.xlauch.com\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1.4 命令\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 启动服务端\nsetsid ./frps -c frps.ini \n\n# 启动客户端\nsetsid ./frpc -c frpc.ini \n\u003C/code\u003E\u003C/pre\u003E"},{"id":"c21f20d","pId":0,"name":"八、框架","parent":"","sort_id":1164215,"order":8,"isParent":true,"extname":null,"open":false},{"id":"1.10 死锁（循环锁）","pId":"2fc41b2","name":"1.10 死锁（循环锁）","parent":"一、并发编程/01  线程基础","order":9,"sort_id":684166,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo死锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E6%AD%BB%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo（死锁）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class DeadLock implements Runnable{\n\n\tprivate String tag;\n\tprivate static Object lock1 = new Object();\n\tprivate static Object lock2 = new Object();\n\t\n\tpublic void setTag(String tag){\n\t\tthis.tag = tag;\n\t}\n\t\n\t@Override\n\tpublic void run() {\n\t\tif(tag.equals(\"a\")){\n\t\t\tsynchronized (lock1) {\n\t\t\t\ttry {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock1执行\");\n\t\t\t\t\tThread.sleep(2000);\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t\tsynchronized (lock2) {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock2执行\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(tag.equals(\"b\")){\n\t\t\tsynchronized (lock2) {\n\t\t\t\ttry {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock2执行\");\n\t\t\t\t\tThread.sleep(2000);\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t\tsynchronized (lock1) {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock1执行\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tDeadLock d1 = new DeadLock();\n\t\td1.setTag(\"a\");\n\t\tDeadLock d2 = new DeadLock();\n\t\td2.setTag(\"b\");\n\t\t \n\t\tThread t1 = new Thread(d1, \"t1\");\n\t\tThread t2 = new Thread(d2, \"t2\");\n\t\t \n\t\tt1.start();\n\t\ttry {\n\t\t\tThread.sleep(500);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\tt2.start();\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1在执行过程中，请求获取t2锁，t2在执行过程中，又请求t1锁，从而导致死锁\u003C/li\u003E\n\u003Cli\u003E死锁问题，在设计程序时就应该避免双方相互持有对方的锁的情况\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"1.9 安装Nginx","pId":"7a86ec7","name":"1.9 安装Nginx","parent":"三、linux /01 软件安装","order":9,"sort_id":987030,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-源码安装\" class=\"anchor\" href=\"#1-%E6%BA%90%E7%A0%81%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E1. 源码安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) 安装nginx所需环境：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install gcc\nyum install pcre-devel\nyum install zlib zlib-devel\nyum install openssl openssl-devel\n或者一键安装：yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(2) 下载nginx压缩包：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Ca href=\"http://nginx.org/en/download.html\"\u003Enginx下载地址\u003C/a\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewget http://nginx.org/download/nginx-1.10.2.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(3) 解压缩：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf nginx-1.10.2.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(4) 编译、安装\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd nginx-1.10.2\n./configure\nmake\nmake install\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(5) 查找nginx安装目录：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewhereis nginx\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(6) 启动Nginx\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd /usr/local/nginx/\ncd sbin\n./nginx\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(7) 打开浏览器，输入ip地址，看到welcome to nginx！即安装成功\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201805/05104005_ylWF.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-yum-安装\" class=\"anchor\" href=\"#2-yum-%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. yum 安装\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install nginx\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E命令\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E#启动\nservice nginx start\n\n#停止\nservice nginx stop\n\n#重启\nservice nginx restart\n\n#另一方式重启\ncd /usr/local/nginx/sbin\n./nginx -s reload\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd /etc/nginx/conf.d\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置tomcat映射\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim tomcat.conf\n\nserver {\n        listen 80;\n        server_name www.xlauch.com;\n        keepalive_timeout 70;\n        proxy_set_header \"Host\" $host:8080;\n        location / {\n                proxy_pass_header Server;\n                proxy_redirect http://$host:8080 http://$host;\n                proxy_pass http://127.0.0.1:8080;\n                proxy_buffer_size 64k;\n                proxy_buffers   32 32k;\n                proxy_busy_buffers_size 128k;\n        }\n        access_log off;\n        log_not_found off;\n}\n\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置frp映射\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim frp.conf\n\nserver {\n        listen 80;\n        server_name *.frp.xlauch.com fxz.xlauch.com xcx.xlauch.com hxy.xlauch.com;\n        keepalive_timeout 70;\n        proxy_set_header \"Host\" $host:9080;\n        location / {\n                proxy_pass_header Server;\n                proxy_redirect http://$host:9080 http://$host;\n                proxy_pass http://127.0.0.1:9080;\n                proxy_buffer_size 64k;\n                proxy_buffers   32 32k;\n                proxy_busy_buffers_size 128k;\n        }\n        access_log off;\n        log_not_found off;\n}\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"97a5782","pId":0,"name":"九、工具类","parent":"","sort_id":1174236,"order":9,"isParent":true,"extname":null,"open":false},{"id":"1.11 锁的粒度","pId":"2fc41b2","name":"1.11 锁的粒度","parent":"一、并发编程/01  线程基础","order":10,"sort_id":684588,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo锁的粒度\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E9%94%81%E7%9A%84%E7%B2%92%E5%BA%A6\"\u003E\u003C/a\u003E1. 示例demo（锁的粒度）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Optimize {\n\n\tpublic void doLongTimeTask(){\n\t\ttry {\n\t\t\t\n\t\t\tSystem.out.println(\"当前线程开始：\" + Thread.currentThread().getName() + \n\t\t\t\t\t\", 正在执行一个较长时间的业务操作，其内容不需要同步\");\n\t\t\tThread.sleep(2000);\n\t\t\t\n\t\t\tsynchronized(this){\n\t\t\t\tSystem.out.println(\"当前线程：\" + Thread.currentThread().getName() + \n\t\t\t\t\t\", 执行同步代码块，对其同步变量进行操作\");\n\t\t\t\tThread.sleep(1000);\n\t\t\t}\n\t\t\tSystem.out.println(\"当前线程结束：\" + Thread.currentThread().getName() +\n\t\t\t\t\t\", 执行完毕\");\n\t\t\t\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal Optimize otz = new Optimize();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\totz.doLongTimeTask();\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\totz.doLongTimeTask();\n\t\t\t}\n\t\t},\"t2\");\n\t\tt1.start();\n\t\tt2.start();\n\t\t\n\t}\n\t\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用synchronized代码块减小锁的粒度，提高性能\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"1.10 安装redis","pId":"7a86ec7","name":"1.10 安装redis","parent":"三、linux /01 软件安装","order":10,"sort_id":988485,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://www.cnblogs.com/zuidongfeng/p/8032505.html\"\u003ECentos7下安装Redis\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"https://redis.io/download\"\u003ERedis 官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-编译安装\" class=\"anchor\" href=\"#2-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. 编译安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E下载源码包\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewget http://download.redis.io/releases/redis-4.0.11.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压安装\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# yum安装gcc依赖 （如果已经有就跳过此步骤）\n[fxz@localhost redis-4.0.11]$ yum install gcc　　\n\n# 解压\n[fxz@localhost redis-4.0.11]$ tar -zxvf redis-4.0.11.tar.gz \n\n# 编译\n[fxz@localhost redis-4.0.11]$ make MALLOC=libc\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/161439_494a2279_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 必须用root安装\n[root@localhost redis-4.0.11]# cd src \u0026amp;\u0026amp; make install\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/161616_487299ce_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-修改配置\" class=\"anchor\" href=\"#3-%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3. 修改配置\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-4.0.11]# cp redis.conf redis.conf.bak\n[root@localhost redis-4.0.11]# mkdir logs\n[root@localhost redis-4.0.11]# vim redis.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eredis.conf\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 设置从后台启动\ndaemonize yes\n\n# 设置日志存放目录\nlogfile \"/usr/local/deve/soft/redis-4.0.11/logs/redis.log\"\n\n# 绑定主机IP\nbind 主机IP\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-启动关闭\" class=\"anchor\" href=\"#4-%E5%90%AF%E5%8A%A8%E5%85%B3%E9%97%AD\"\u003E\u003C/a\u003E4. 启动、关闭\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 指定配置文件启动\n[root@localhost src]# ./redis-server ../redis.conf\n\n[root@localhost src]# ps -ef | grep redis\nroot      10562      1  0 16:27 ?        00:00:00 ./redis-server 127.0.0.1:6379\nroot      10575  10280  0 16:27 pts/0    00:00:00 grep --color=auto redis\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E连接\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 进入客户端\n[root@localhost src]# ./redis-cli \n\n# 查看所有键\n127.0.0.1:6379\u0026gt; key *\n(error) ERR unknown command `key`, with args beginning with: `*`, \n\n# 设值\n127.0.0.1:6379\u0026gt; set name fxz\nOK\n\n# 取值\n127.0.0.1:6379\u0026gt; get name\n\"fxz\"\n127.0.0.1:6379\u0026gt; \n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关闭\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 退出客户端\n127.0.0.1:6379\u0026gt; quit\n\n# 退出服务端方式一\n[root@localhost src]# ./redis-cli shutdown\n\n# 退出服务端方式二\n[root@localhost src]# ./redis-server ../redis.conf\n[root@localhost src]# ps -ef | grep redis\nroot      10691      1  0 16:32 ?        00:00:00 ./redis-server 127.0.0.1:6379\nroot      10696  10280  0 16:32 pts/0    00:00:00 grep --color=auto redis\n[root@localhost src]# kill -9 10691\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-数据保存\" class=\"anchor\" href=\"#5-%E6%95%B0%E6%8D%AE%E4%BF%9D%E5%AD%98\"\u003E\u003C/a\u003E5. 数据保存\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-4.0.11]# vim redis.conf\n\n\n# 默认文件名\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# 数据存放路径\ndir ./\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/163721_7f3d9314_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"常见问题\" class=\"anchor\" href=\"#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E常见问题\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E/bin/sh: cc: command not found\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esudo yum -y install gcc gcc-c++ libstdc++-devel \nmake MALLOC=libc\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.12 volatile关键字","pId":"2fc41b2","name":"1.12 volatile关键字","parent":"一、并发编程/01  线程基础","order":11,"sort_id":684683,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo1\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo1\"\u003E\u003C/a\u003E1. 示例demo1\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class RunThread extends Thread{\n\n\tprivate volatile boolean isRunning = true;\n\tprivate void setRunning(boolean isRunning){\n\t\tthis.isRunning = isRunning;\n\t}\n\t\n\tpublic void run(){\n\t\tSystem.out.println(\"进入run方法..\");\n\t\tint i = 0;\n\t\twhile(isRunning == true){\n\t\t\t//..\n\t\t}\n\t\tSystem.out.println(\"线程停止\");\n\t}\n\t\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\tRunThread rt = new RunThread();\n\t\trt.start();\n\t\tThread.sleep(1000);\n\t\trt.setRunning(false);\n\t\tSystem.out.println(\"isRunning的值已经被设置了false\");\n\t}\n\t\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E如果变量\"isRunning\"没有volatile 进行修饰，那么进程就无法停止，因为main线程与rt线程中isRunning无法共用\u003C/li\u003E\n\u003Cli\u003E使用\"volatile\"关键字对变量进行修饰后，可以让\"isRunning\"可以在多个线程中相互可见\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"1.11 安装docker","pId":"7a86ec7","name":"1.11 安装docker","parent":"三、linux /01 软件安装","order":11,"sort_id":1031999,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"一在线下载docker\" class=\"anchor\" href=\"#%E4%B8%80%E5%9C%A8%E7%BA%BF%E4%B8%8B%E8%BD%BDdocker\"\u003E\u003C/a\u003E一、在线下载docker\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/qingyunzong/p/9011006.html\"\u003ECentOS7 安装Docker\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum update\n\nyum install -y epel-release\n\nyum install docker-io       # 安装docker\n\nchkconfig docker on         # 加入开机启动\n\nsystemctl start docker      # 启动docker服务\n\nsystemctl restart docker      # 重启docker服务\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"二测试验证\" class=\"anchor\" href=\"#%E4%BA%8C%E6%B5%8B%E8%AF%95%E9%AA%8C%E8%AF%81\"\u003E\u003C/a\u003E二、测试验证\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 查看版本\ndocker -v\n\n#运行容器\ndocker run hello-world\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"三设置镜像\" class=\"anchor\" href=\"#%E4%B8%89%E8%AE%BE%E7%BD%AE%E9%95%9C%E5%83%8F\"\u003E\u003C/a\u003E三、设置镜像\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E参考 \u003Ca href=\"https://cr.console.aliyun.com/cn-shenzhen/mirrors\"\u003Ehttps://cr.console.aliyun.com/cn-shenzhen/mirrors\u003C/a\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evi /etc/docker/daemon.json\n\n{\n  \"registry-mirrors\": [\"https://aj2rgad5.mirror.aliyuncs.com\"]\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E立即生效\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E#使生效\nsudo systemctl daemon-reload\n\n#重启docker服务\nsudo systemctl restart docker\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"常见问题\" class=\"anchor\" href=\"#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E常见问题\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1-error-starting-daemon-selinux-is-not-supported-with-the-overlay2-graph-driver-on-this-kernel-eithe\" class=\"anchor\" href=\"#1-error-starting-daemon-selinux-is-not-supported-with-the-overlay2-graph-driver-on-this-kernel-eithe\"\u003E\u003C/a\u003E1. Error starting daemon: SELinux is not supported with the overlay2 graph driver on this kernel. Eithe\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Evi /etc/sysconfig/docker\n \n\nOPTIONS='--selinux-enabled=false  --log-driver=journald --signature-verification=false'\nif [ -z \"${DOCKER_CERT_PATH}\" ]; then\n    DOCKER_CERT_PATH=/etc/docker\nfi\n\n:wq \n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.13 Atomic原子变量","pId":"2fc41b2","name":"1.13 Atomic原子变量","parent":"一、并发编程/01  线程基础","order":12,"sort_id":684860,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo1\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo1\"\u003E\u003C/a\u003E1. 示例demo1\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class VolatileNoAtomic extends Thread{\n\t//private static volatile int count;\n\tprivate static AtomicInteger count = new AtomicInteger(0);\n\tprivate static void addCount(){\n\t\tfor (int i = 0; i \u0026lt; 1000; i++) {\n\t\t\t//count++ ;\n\t\t\tcount.incrementAndGet();\n\t\t}\n\t\tSystem.out.println(count);\n\t}\n\t\n\tpublic void run(){\n\t\taddCount();\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tVolatileNoAtomic[] arr = new VolatileNoAtomic[100];\n\t\tfor (int i = 0; i \u0026lt; 10; i++) {\n\t\t\tarr[i] = new VolatileNoAtomic();\n\t\t}\n\t\t\n\t\tfor (int i = 0; i \u0026lt; 10; i++) {\n\t\t\tarr[i].start();\n\t\t}\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Evolatile关键字不具备synchronized关键字的原子性（同步），每次结果都不一样\u003C/li\u003E\n\u003Cli\u003E使用AtomicInteger 可以保证原子性，最终结果都为1000*10\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例demo2\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8Bdemo2\"\u003E\u003C/a\u003E2. 示例demo2\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class AtomicUse {\n\n\tprivate static AtomicInteger count = new AtomicInteger(0);\n\t\n\t//多个addAndGet在一个方法内是非原子性的，需要加synchronized进行修饰，保证4个addAndGet整体原子性\n\t/**synchronized*/\n\tpublic synchronized int multiAdd(){\n\t\t\ttry {\n\t\t\t\tThread.sleep(100);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\tcount.addAndGet(1);\n\t\t\tcount.addAndGet(2);\n\t\t\tcount.addAndGet(3);\n\t\t\tcount.addAndGet(4); //+10\n\t\t\treturn count.get();\n\t}\n\t\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal AtomicUse au = new AtomicUse();\n\n\t\tList\u0026lt;Thread\u0026gt; ts = new ArrayList\u0026lt;Thread\u0026gt;();\n\t\tfor (int i = 0; i \u0026lt; 100; i++) {\n\t\t\tts.add(new Thread(new Runnable() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tSystem.out.println(au.multiAdd());\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\tfor(Thread t : ts){\n\t\t\tt.start();\n\t\t}\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E多个addAndGet在一个方法内是非原子性的，需要加synchronized进行修饰，保证4个addAndGet整体原子性\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"1.12 安装webterminal","pId":"7a86ec7","name":"1.12 安装webterminal","parent":"三、linux /01 软件安装","order":12,"sort_id":1032058,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"一参考资料\" class=\"anchor\" href=\"#%E4%B8%80%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E一、参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/jimmy201602/webterminal\"\u003Ewebterminal git官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"二安装\" class=\"anchor\" href=\"#%E4%BA%8C%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E二、安装\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 国内请使用阿里云镜像\ndocker pull registry.cn-hangzhou.aliyuncs.com/webterminal/webterminal \ndocker run -itd -p 80:80 registry.cn-hangzhou.aliyuncs.com/webterminal/webterminal \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"三登录\" class=\"anchor\" href=\"#%E4%B8%89%E7%99%BB%E5%BD%95\"\u003E\u003C/a\u003E三、登录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eusername: admin\npassword: password!23456\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.13 安装VNC","pId":"7a86ec7","name":"1.13 安装VNC","parent":"三、linux /01 软件安装","order":13,"sort_id":1035589,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"0参考资料\" class=\"anchor\" href=\"#0%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E0、参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.linuxidc.com/Linux/2017-05/143346.htm\"\u003ECentOS7.1安装VNC，让Win7远程桌面Linux\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"https://jingyan.baidu.com/article/86f4a73e9c937537d652691e.html\"\u003ECentOS 7.2 安装配置VNC\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1安装x-window\" class=\"anchor\" href=\"#1%E5%AE%89%E8%A3%85x-window\"\u003E\u003C/a\u003E1、安装X-Window\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum check-update\nyum groupinstall \"X Window System\"\nyum install gnome-classic-session gnome-terminal nautilus-open-terminal control-center liberation-mono-fonts\nunlink /etc/systemd/system/default.target\nln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target\nreboot #重启机器\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2安装vncserver\" class=\"anchor\" href=\"#2%E5%AE%89%E8%A3%85vncserver\"\u003E\u003C/a\u003E2、安装VNCServer\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E#检查是否安装VNC \nrpm -q tigervnc tigervnc-server\n\nyum install tigervnc tigervnc-server\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3配置nvc\" class=\"anchor\" href=\"#3%E9%85%8D%E7%BD%AEnvc\"\u003E\u003C/a\u003E3、配置NVC\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 将/lib/systemd/system/vncserver@.service文件复制一份\n\ncp /lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:1.service\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4编辑刚刚我们复制得新文件\" class=\"anchor\" href=\"#4%E7%BC%96%E8%BE%91%E5%88%9A%E5%88%9A%E6%88%91%E4%BB%AC%E5%A4%8D%E5%88%B6%E5%BE%97%E6%96%B0%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E4、编辑刚刚我们复制得新文件\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E设置root用户\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/systemd/system/vncserver@:1.service\n\n\n# 把\u0026lt;USER\u0026gt; 替换成root\n# Clean any existing files in /tmp/.X11-unix environment\nExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n#ExecStart=/usr/sbin/runuser -l root -c \"/usr/bin/vncserver %i\"\n#PIDFile=/root/.vnc/%H%i.pid\n\nExecStart=/sbin/runuser -l root -c \"/usr/bin/vncserver %i\" \nPIDFile=/root/.vnc/%H%i.pid\n\nExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E设置非root用户\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# Clean any existing files in /tmp/.X11-unix environment\nExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n#ExecStart=/usr/sbin/runuser -l root -c \"/usr/bin/vncserver %i\"\n#PIDFile=/root/.vnc/%H%i.pid\n\nExecStart=/sbin/runuser -l fxz -c \"/usr/bin/vncserver %i\"\nPIDFile=/home/fxz/.vnc/%H%i.pid\n\nExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E设置非root用户密码\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esu fxz\nvncpasswd\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改VNC 分辨率\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost ~]# vi /usr/bin/vncserver \n\n$geometry = “1280×1024″;  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5重新加载-systemd\" class=\"anchor\" href=\"#5%E9%87%8D%E6%96%B0%E5%8A%A0%E8%BD%BD-systemd\"\u003E\u003C/a\u003E5、重新加载 systemd\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E#由于在systemd中添加了东东,得让系统重新加载\nsystemctl daemon-reload\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6设置vncserver开机自启动\" class=\"anchor\" href=\"#6%E8%AE%BE%E7%BD%AEvncserver%E5%BC%80%E6%9C%BA%E8%87%AA%E5%90%AF%E5%8A%A8\"\u003E\u003C/a\u003E6、设置VNCServer开机自启动\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\n# VNCServer开机自启动\nsystemctl enable vncserver@:1.service\n\n# 启动\nsystemctl start vncserver@:1.service\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"7设置密码8898081\" class=\"anchor\" href=\"#7%E8%AE%BE%E7%BD%AE%E5%AF%86%E7%A0%818898081\"\u003E\u003C/a\u003E7、设置密码（8898081）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Evncpasswd\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"8客户端连接\" class=\"anchor\" href=\"#8%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BF%9E%E6%8E%A5\"\u003E\u003C/a\u003E8、客户端连接\u003C/h3\u003E\n\u003Cp\u003E下载VNC Viewer ：\u003Ca href=\"http://www.realvnc.com/download/viewer/\"\u003Ehttp://www.realvnc.com/download/viewer/\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1123/144939_f95433b5_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"9常见错误\" class=\"anchor\" href=\"#9%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF\"\u003E\u003C/a\u003E9、常见错误\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"job-for-vncserver1service-failed-because-the-control-process-exited-with-error-code-see-systemctl-status-vncserver1service-and-journalctl--xe-for-details\" class=\"anchor\" href=\"#job-for-vncserver1service-failed-because-the-control-process-exited-with-error-code-see-systemctl-status-vncserver1service-and-journalctl--xe-for-details\"\u003E\u003C/a\u003EJob for vncserver@:1.service failed because the control process exited with error code. See \"systemctl status vncserver@:1.service\" and \"journalctl -xe\" for details.\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Erm -f -R /tmp/.X11-unix/\n\nsystemctl enable vncserver@:1.service\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"1.14 安装gogs ","pId":"7a86ec7","name":"1.14 安装gogs ","parent":"三、linux /01 软件安装","order":14,"sort_id":1096535,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"参考资料\" class=\"anchor\" href=\"#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://gogs.io/docs/installation/configuration_and_run\"\u003Egogs 说明文档\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-环境要求\" class=\"anchor\" href=\"#1-%E7%8E%AF%E5%A2%83%E8%A6%81%E6%B1%82\"\u003E\u003C/a\u003E1. 环境要求\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E数据库（选择以下一项）：\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Ca href=\"http://dev.mysql.com\"\u003EMySQL\u003C/a\u003E：版本 \u0026gt;= 5.7\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"http://www.postgresql.org/\"\u003EPostgreSQL\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"https://en.wikipedia.org/wiki/Microsoft_SQL_Server\"\u003EMSSQL\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\n\u003Ca href=\"https://github.com/pingcap/tidb\"\u003ETiDB\u003C/a\u003E（实验性支持，使用 MySQL 协议连接）\u003C/li\u003E\n\u003Cli\u003E或者 \u003Cstrong\u003E什么都不安装\u003C/strong\u003E 直接使用 SQLite3\u003C/li\u003E\n\u003C/ul\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Ca href=\"http://git-scm.com/\"\u003Egit\u003C/a\u003E（bash）：\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E服务端和客户端均需版本 \u0026gt;= 1.7.1\u003C/li\u003E\n\u003Cli\u003EWindows 系统建议使用最新版\u003C/li\u003E\n\u003C/ul\u003E\n\u003C/li\u003E\n\u003Cli\u003ESSH 服务器：\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E如果您只使用 HTTP/HTTPS 的话请忽略此项\u003C/strong\u003E\u003C/li\u003E\n\u003Cli\u003E如果您选择在 Windows 系统使用内置 SSH 服务器，请确保添加 \u003Ccode\u003Essh-keygen\u003C/code\u003E 到您的 \u003Ccode\u003E%PATH%\u003C/code\u003E 环境变量中\u003C/li\u003E\n\u003Cli\u003E推荐 Windows 系统使用 \u003Ca href=\"http://docs.oracle.com/cd/E24628_01/install.121/e22624/preinstall_req_cygwin_ssh.htm\"\u003ECygwin OpenSSH\u003C/a\u003E 或 \u003Ca href=\"https://www.itefix.net/copssh\"\u003ECopssh\u003C/a\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-安装数据库\" class=\"anchor\" href=\"#2-%E5%AE%89%E8%A3%85%E6%95%B0%E6%8D%AE%E5%BA%93\"\u003E\u003C/a\u003E2. 安装数据库\u003C/h3\u003E\n\u003Cp\u003E请根据您的选择进行安装：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Ca href=\"http://dev.mysql.com/downloads/mysql/\"\u003EMySQL\u003C/a\u003E（引擎：INNODB）\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"http://www.postgresql.org/download/\"\u003EPostgreSQL\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003E注意事项\u003C/strong\u003E 您可以使用 \u003Ccode\u003Eetc/mysql.sql\u003C/code\u003E 来自动创建名为 \u003Ccode\u003Egogs\u003C/code\u003E 的数据库。如果您选择手动创建，请务必将编码设置为 \u003Ccode\u003Eutf8mb4\u003C/code\u003E。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-二进制安装\" class=\"anchor\" href=\"#3-%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E3. 二进制安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压压缩包。\u003C/li\u003E\n\u003Cli\u003E使用命令 cd 进入到刚刚创建的目录。\u003C/li\u003E\n\u003Cli\u003E执行命令 nohup ./gogs web \u0026amp; ，默认端口3000\u003C/li\u003E\n\u003Cli\u003E然后访问 /install 来完成首次运行的配置工作\u003C/li\u003E\n\u003C/ul\u003E"},{"id":"5c8b4c4","pId":0,"name":"十、其它","parent":"","sort_id":1214571,"order":14,"isParent":true,"extname":null,"open":false},{"id":"1. 利用jib打包docker-file","pId":"91330e0","name":"1. 利用jib打包docker-file","parent":"七、容器、集成/01 docker","order":15,"sort_id":1331224,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"1-打包war\" class=\"anchor\" href=\"#1-%E6%89%93%E5%8C%85war\"\u003E\u003C/a\u003E1. 打包war\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;com.google.cloud.tools\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;jib-maven-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;version\u0026gt;1.0.0\u0026lt;/version\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t\t\u0026lt;from\u0026gt;\n\t\t\t\u0026lt;!--base image--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;tomcat:8.5-jre8-alpine\u0026lt;/image\u0026gt;\n\t\t\u0026lt;/from\u0026gt;\n\t\t\u0026lt;to\u0026gt;\n\t\t\t\u0026lt;!--目标镜像registry地址，为了方便测试，你需要换成自己的地址，如果你的网络不好，可以选用国内加速器，比如阿里云的--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;registry.cn-hangzhou.aliyuncs.com/xlauch/xlauch-dubbo\u0026lt;/image\u0026gt;\n\t\t\t\u0026lt;auth\u0026gt;\n\t\t\t\t\u0026lt;username\u0026gt;hi35361525@aliyun.com\u0026lt;/username\u0026gt;\n\t\t\t\t\u0026lt;password\u0026gt;xiao8898081\u0026lt;/password\u0026gt;\n\t\t\t\u0026lt;/auth\u0026gt;\n\t\t\t\u0026lt;tags\u0026gt;\n\t\t\t\t\u0026lt;tag\u0026gt;1.0\u0026lt;/tag\u0026gt;\n\t\t\t\t\u0026lt;tag\u0026gt;latest\u0026lt;/tag\u0026gt;\n\t\t\t\u0026lt;/tags\u0026gt;\n\t\t\u0026lt;/to\u0026gt;\n\t\t\u0026lt;container\u0026gt;\n\t\t\t\u0026lt;appRoot\u0026gt;/usr/local/tomcat/webapps/ROOT\u0026lt;/appRoot\u0026gt;\n\t\t\u0026lt;/container\u0026gt;\n\n\t\u0026lt;/configuration\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t\t\u0026lt;execution\u0026gt;\n\t\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\t\u0026lt;goals\u0026gt;\n\t\t\t\t\u0026lt;goal\u0026gt;build\u0026lt;/goal\u0026gt;\n\t\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n\u0026lt;/plugin\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-打包jar\" class=\"anchor\" href=\"#2-%E6%89%93%E5%8C%85jar\"\u003E\u003C/a\u003E2. 打包jar\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\n\u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;com.google.cloud.tools\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;jib-maven-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;version\u0026gt;1.0.0\u0026lt;/version\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t\t\u0026lt;from\u0026gt;\n\t\t\t\u0026lt;!--base image--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;openjdk:alpine\u0026lt;/image\u0026gt;\n\t\t\u0026lt;/from\u0026gt;\n\t\t\u0026lt;to\u0026gt;\n\t\t\t\u0026lt;!--目标镜像registry地址，为了方便测试，你需要换成自己的地址，如果你的网络不好，可以选用国内加速器，比如阿里云的--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;registry.cn-hangzhou.aliyuncs.com/xlauch/xlauch-dubbo\u0026lt;/image\u0026gt;\n                        \u0026lt;auth\u0026gt;\n                            \u0026lt;username\u0026gt;hi35361525@aliyun.com\u0026lt;/username\u0026gt;\n                            \u0026lt;password\u0026gt;xiao8898081\u0026lt;/password\u0026gt;\n                        \u0026lt;/auth\u0026gt;\n                        \u0026lt;tags\u0026gt;\n                            \u0026lt;tag\u0026gt;1.0\u0026lt;/tag\u0026gt;\n                            \u0026lt;tag\u0026gt;latest\u0026lt;/tag\u0026gt;\n                        \u0026lt;/tags\u0026gt; \n\t\t\u0026lt;/to\u0026gt;\n\t\t\u0026lt;container\u0026gt;\n\t\t\t\u0026lt;mainClass\u0026gt;com.i84.insect.svc.bootstrap.SvcStart\u0026lt;/mainClass\u0026gt;\n\t\t\u0026lt;/container\u0026gt;\n\t\u0026lt;/configuration\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t\t\u0026lt;execution\u0026gt;\n\t\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\t\u0026lt;goals\u0026gt;\n\t\t\t\t\u0026lt;goal\u0026gt;build\u0026lt;/goal\u0026gt;\n\t\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n\u0026lt;/plugin\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E"},{"id":"185375b","pId":"c21f20d","name":"04 springcloud-alibaba","parent":"八、框架","sort_id":1347358,"order":16,"isParent":true,"extname":null,"open":false},{"id":"4.1 环境准备","pId":"185375b","name":"4.1 环境准备","parent":"八、框架/04 springcloud-alibaba","order":17,"sort_id":1347359,"extname":".md","isParent":false,"isHidden":false,"content":"\u003Ch3\u003E\n\u003Ca id=\"一参考资料\" class=\"anchor\" href=\"#%E4%B8%80%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E一、参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://nacos.io/zh-cn/\"\u003Enacos官网\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==\u0026amp;mid=2247486943\u0026amp;idx=1\u0026amp;sn=fccce227cac0843cca1f18716b0f9b46\u0026amp;chksm=9bd0a047aca72951a1a945e51cc28e0e373b75080281e7add78a964f71ec888248164e80bd40\u0026amp;scene=0\u0026amp;xtrack=1#rd\"\u003E程序猿DD\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://www.bilibili.com/video/av45084065\"\u003Epigx  spring cloud alibaba  系列教程\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/spring-cloud-incubator/spring-cloud-alibaba/wiki/Nacos-discovery\"\u003E官方git教程\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"二特别注意版本兼容问题\" class=\"anchor\" href=\"#%E4%BA%8C%E7%89%B9%E5%88%AB%E6%B3%A8%E6%84%8F%E7%89%88%E6%9C%AC%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E二、特别注意（版本兼容问题）\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003ESpring Boot\u003C/th\u003E\n\u003Cth\u003ESpring Cloud\u003C/th\u003E\n\u003Cth\u003ESpring Cloud Alibaba\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2.1.x\u003C/td\u003E\n\u003Ctd\u003EGreenwich\u003C/td\u003E\n\u003Ctd\u003E0.2.2（还未RELEASE）\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2.0.x\u003C/td\u003E\n\u003Ctd\u003EFinchley\u003C/td\u003E\n\u003Ctd\u003E0.2.1\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1.5.x\u003C/td\u003E\n\u003Ctd\u003EEdgware\u003C/td\u003E\n\u003Ctd\u003E0.1.1\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1.5.x\u003C/td\u003E\n\u003Ctd\u003EDalston\u003C/td\u003E\n\u003Ctd\u003E0.1.1\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"}],"content":{"1027404":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/feiyun126/p/7248989.html\"\u003Eredis4集群\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-下载redis-401并解压\" class=\"anchor\" href=\"#2-%E4%B8%8B%E8%BD%BDredis-401%E5%B9%B6%E8%A7%A3%E5%8E%8B\"\u003E\u003C/a\u003E2. 下载redis-4.0.1并解压\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E解压目录：/usr/local/redis-4.0.1\n建立软连接：ln -s redis-4.0.1 redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-编译安装\" class=\"anchor\" href=\"#3-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E3. 编译安装\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E指定安装目录到:/usr/local/redis\n\nmake \u0026amp;\u0026amp; make install PREFIX=/usr/local/redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-节点准备\" class=\"anchor\" href=\"#4-%E8%8A%82%E7%82%B9%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E4. 节点准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E节点分配信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E主机\u003C/th\u003E\n\u003Cth\u003E端口\u003C/th\u003E\n\u003Cth\u003E主从\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Enode1_192.168.222.132\u003C/td\u003E\n\u003Ctd\u003E7001\u003C/td\u003E\n\u003Ctd\u003E主\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Enode1_192.168.222.132\u003C/td\u003E\n\u003Ctd\u003E7002\u003C/td\u003E\n\u003Ctd\u003E从\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Enode2_192.168.222.133\u003C/td\u003E\n\u003Ctd\u003E7003\u003C/td\u003E\n\u003Ctd\u003E主\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Enode2_192.168.222.133\u003C/td\u003E\n\u003Ctd\u003E7004\u003C/td\u003E\n\u003Ctd\u003E从\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Enode3_192.168.222.134\u003C/td\u003E\n\u003Ctd\u003E7005\u003C/td\u003E\n\u003Ctd\u003E主\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Enode3_192.168.222.135\u003C/td\u003E\n\u003Ctd\u003E7006\u003C/td\u003E\n\u003Ctd\u003E从\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置节点信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# node1服务器:\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7001\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7002\n\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7001\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7002\n\n# node2服务器:\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7003\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7004\n\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7003\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7004\n\n# node3服务器:\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7005\nmkdir -p /usr/loca/deve/sofr/redis_cluster/7006\n\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7005\ncp /usr/local/redis/redis.conf /usr/loca/deve/sofr/redis_cluster/7006\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-修改redisconfig\" class=\"anchor\" href=\"#5-%E4%BF%AE%E6%94%B9redisconfig\"\u003E\u003C/a\u003E5. 修改redis.config\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E值\u003C/th\u003E\n\u003Cth\u003E说明\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Eport\u003C/td\u003E\n\u003Ctd\u003E7000\u003C/td\u003E\n\u003Ctd\u003E端口号\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ebind\u003C/td\u003E\n\u003Ctd\u003E本机ip\u003C/td\u003E\n\u003Ctd\u003E根据本机所在的IP或hostname去配制 node1 node2 node3\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Edaemonize\u003C/td\u003E\n\u003Ctd\u003Eyes\u003C/td\u003E\n\u003Ctd\u003Eredis后台运行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Edir\u003C/td\u003E\n\u003Ctd\u003E/usr/local/deve/soft/redis-cluster/700*/\u003C/td\u003E\n\u003Ctd\u003E指定数据文件存放目录\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Epidfile\u003C/td\u003E\n\u003Ctd\u003E/var/run/redis_7000.pid\u003C/td\u003E\n\u003Ctd\u003Epidfile文件对应7000,7001,7002,7003,7004,7005\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ecluster-enabled\u003C/td\u003E\n\u003Ctd\u003Eyes\u003C/td\u003E\n\u003Ctd\u003E开启集群  把注释#去掉\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Ecluster-config-file\u003C/td\u003E\n\u003Ctd\u003Enodes_7000.conf\u003C/td\u003E\n\u003Ctd\u003E集群的配置  配置文件首次启动自动生成 7000,7001,7002,7003,7004,7005\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ecluster-node-timeout\u003C/td\u003E\n\u003Ctd\u003E15000\u003C/td\u003E\n\u003Ctd\u003E请求超时  默认15秒，可自行设置\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Eappendonly\u003C/td\u003E\n\u003Ctd\u003Eyes\u003C/td\u003E\n\u003Ctd\u003Eaof日志开启  有需要就开启，它会每次写操作都记录一条日志\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Elogfile\u003C/td\u003E\n\u003Ctd\u003E/usr/local/deve/soft/redis-cluster//7001.log\u003C/td\u003E\n\u003Ctd\u003E日志目录\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-安装ruby环境\" class=\"anchor\" href=\"#6-%E5%AE%89%E8%A3%85ruby%E7%8E%AF%E5%A2%83\"\u003E\u003C/a\u003E6. 安装ruby环境\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install -y ruby\nyum install -y rubygems\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"7-安装ruby的包\" class=\"anchor\" href=\"#7-%E5%AE%89%E8%A3%85ruby%E7%9A%84%E5%8C%85\"\u003E\u003C/a\u003E7. 安装ruby的包\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Egem install redis\n\n如果不成功需要去下载后安装\n下载地址\nhttps://rubygems.org/gems/redis/versions/4.0.0.rc1\nhttps://rubygems.org/downloads/redis-4.0.0.rc1.gem\n\n安装命令：gem install -l ./redis-4.0.0.rc1.gem\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"8-启动各个节点\" class=\"anchor\" href=\"#8-%E5%90%AF%E5%8A%A8%E5%90%84%E4%B8%AA%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E8. 启动各个节点\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# node1服务器:\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7001/redis.conf\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7002/redis.conf\n\n# node2服务器:\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7003/redis.conf\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7004/redis.conf\n\n# node3服务器:\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7005/redis.conf\n/usr/local/redis/bin/redis-server /usr/loca/deve/sofr/redis_cluster/7006/redis.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"9-检查各节点是否启动\" class=\"anchor\" href=\"#9-%E6%A3%80%E6%9F%A5%E5%90%84%E8%8A%82%E7%82%B9%E6%98%AF%E5%90%A6%E5%90%AF%E5%8A%A8\"\u003E\u003C/a\u003E9. 检查各节点是否启动\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E查看进程\nps -ef | grep redis\n\n查看端口\nnetstat -tnlp | grep redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"10-创建集群\" class=\"anchor\" href=\"#10-%E5%88%9B%E5%BB%BA%E9%9B%86%E7%BE%A4\"\u003E\u003C/a\u003E10. 创建集群\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 进入node1的bin目录下,执行以下脚本\n./redis-trib.rb  create  --replicas  1  node1:7001 node1:7002  node2:7003  node2:7004  node3:7005  node3:7006\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E--replicas  1 : 主/从=1\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# ./redis-trib.rb  create  --replicas  1  127.0.0.1:7001 127.0.0.1:7002  127.0.0.1:7003  127.0.0.1:7004  127.0.0.1:7005  127.0.0.1:7006\n\n./redis-trib.rb  create  --replicas  1  127.0.0.1:7001 127.0.0.1:7002  127.0.0.1:7003  127.0.0.1:7004  127.0.0.1:7005  127.0.0.1:7006\n\n./redis-trib.rb  create  --replicas  1  192.168.222.129:7001 192.168.222.129:7002  192.168.222.129:7003  192.168.222.129:7004  192.168.222.129:7005  192.168.222.129:7006\n\n\n\u0026gt;\u0026gt;\u0026gt; Creating cluster\n\u0026gt;\u0026gt;\u0026gt; Performing hash slots allocation on 6 nodes...\nUsing 3 masters:\n127.0.0.1:7001\n127.0.0.1:7002\n127.0.0.1:7003\nAdding replica 127.0.0.1:7005 to 127.0.0.1:7001\nAdding replica 127.0.0.1:7006 to 127.0.0.1:7002\nAdding replica 127.0.0.1:7004 to 127.0.0.1:7003\n\u0026gt;\u0026gt;\u0026gt; Trying to optimize slaves allocation for anti-affinity\n[WARNING] Some slaves are in the same host as their master\nM: e0be2ed1522678a87ac7c7d717404a41cff8c324 127.0.0.1:7001\n   slots:0-5460 (5461 slots) master\nM: 12a9e2e40beb5fa2799715fa35b8d770dd4a4669 127.0.0.1:7002\n   slots:5461-10922 (5462 slots) master\nM: 7415681580ed3f02f98abd36816f45d38d462198 127.0.0.1:7003\n   slots:10923-16383 (5461 slots) master\nS: af1103565bbeae4147e931bad6699df121040cae 127.0.0.1:7004\n   replicates 7415681580ed3f02f98abd36816f45d38d462198\nS: 3bea7a226f979b2741e2d4eea6934d9342cababd 127.0.0.1:7005\n   replicates e0be2ed1522678a87ac7c7d717404a41cff8c324\nS: c1051cc7b154a5a536bce536865a06d67a618218 127.0.0.1:7006\n   replicates 12a9e2e40beb5fa2799715fa35b8d770dd4a4669\nCan I set the above configuration? (type 'yes' to accept): yes\n\u0026gt;\u0026gt;\u0026gt; Nodes configuration updated\n\u0026gt;\u0026gt;\u0026gt; Assign a different config epoch to each node\n\u0026gt;\u0026gt;\u0026gt; Sending CLUSTER MEET messages to join the cluster\nWaiting for the cluster to join...\n\u0026gt;\u0026gt;\u0026gt; Performing Cluster Check (using node 127.0.0.1:7001)\nM: e0be2ed1522678a87ac7c7d717404a41cff8c324 127.0.0.1:7001\n   slots:0-5460 (5461 slots) master\n   1 additional replica(s)\nS: af1103565bbeae4147e931bad6699df121040cae 127.0.0.1:7004\n   slots: (0 slots) slave\n   replicates 7415681580ed3f02f98abd36816f45d38d462198\nS: c1051cc7b154a5a536bce536865a06d67a618218 127.0.0.1:7006\n   slots: (0 slots) slave\n   replicates 12a9e2e40beb5fa2799715fa35b8d770dd4a4669\nS: 3bea7a226f979b2741e2d4eea6934d9342cababd 127.0.0.1:7005\n   slots: (0 slots) slave\n   replicates e0be2ed1522678a87ac7c7d717404a41cff8c324\nM: 7415681580ed3f02f98abd36816f45d38d462198 127.0.0.1:7003\n   slots:10923-16383 (5461 slots) master\n   1 additional replica(s)\nM: 12a9e2e40beb5fa2799715fa35b8d770dd4a4669 127.0.0.1:7002\n   slots:5461-10922 (5462 slots) master\n   1 additional replica(s)\n[OK] All nodes agree about slots configuration.\n\u0026gt;\u0026gt;\u0026gt; Check for open slots...\n\u0026gt;\u0026gt;\u0026gt; Check slots coverage...\n[OK] All 16384 slots covered.\n[root@localhost src]# \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"11-验证集群\" class=\"anchor\" href=\"#11-%E9%AA%8C%E8%AF%81%E9%9B%86%E7%BE%A4\"\u003E\u003C/a\u003E11. 验证集群\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E进入每台服务器的redis/src目录,记住参数  -c不可以少\n\nredis-cli -h node1 -p 7001 -c\n\nredis-cli -h node2 -p 7003 -c\n\nredis-cli -h node3 -p 7005 -c\n\u003C/code\u003E\u003C/pre\u003E","672495":"\u003Ch3\u003E\n\u003Ca id=\"1-什么叫线程安全\" class=\"anchor\" href=\"#1-%E4%BB%80%E4%B9%88%E5%8F%AB%E7%BA%BF%E7%A8%8B%E5%AE%89%E5%85%A8\"\u003E\u003C/a\u003E1. 什么叫线程安全：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E如果你的代码所在的进程中有多个线程在同时运行，而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的，而且其他的变量的值也和预期的是一样的，\n就是线程安全的。\u003C/li\u003E\n\u003Cli\u003E或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。\n线程安全问题都是由全局变量及静态变量引起的。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-测试demo\" class=\"anchor\" href=\"#2-%E6%B5%8B%E8%AF%95demo\"\u003E\u003C/a\u003E2. 测试demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.thread;\n\n\n/**\n * \u0026lt;p\u0026gt;\n *  类描述 :  synchronized：可以在任意对象及方法上加锁，而加锁的这段代码称为\"互斥区\"或\"临界区\"\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/21\n */\npublic class MyThread extends Thread {\n\n    private int count = 5;\n\n    //synchronized加锁\n    @Override\n    public synchronized void run() {\n        count--;\n        String name = MyThread.currentThread().getName();\n        System.out.println(\"name :\" + name + \" =========  count: \" + count);\n    }\n\n    public static void  main(String[] args) {\n        MyThread myThread = new MyThread() ;\n        Thread t1 = new Thread(myThread , \"t1\") ;\n        Thread t2 = new Thread(myThread , \"t2\") ;\n        Thread t3 = new Thread(myThread , \"t3\") ;\n        Thread t4 = new Thread(myThread , \"t4\") ;\n        Thread t5 = new Thread(myThread , \"t5\") ;\n\n        t1.start();\n        t2.start();\n        t3.start();\n        t4.start();\n        t5.start();\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当run方法不进行synchronized加锁时，输出结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0821/145305_fa3d3b06_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当run方法进行synchronized加锁时，输出结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0821/145329_e1c99369_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例说明\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E3. 示例说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E当多个线程访问MyThread的run方法时，以排队的方式进行处理（这里排队是按照CPU分配的先后顺序而定）\u003C/li\u003E\n\u003Cli\u003E一个线程想要执行synchronized修饰的方法时，首先要获得锁，只有获得锁才能执行synchronized代码体内容，这个线程会一直尝试，直到获得锁为止\u003C/li\u003E\n\u003Cli\u003E多个线程竞争一把锁，会导致锁竞争\u003C/li\u003E\n\u003C/ul\u003E","685536":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1demo1\" class=\"anchor\" href=\"#1demo1\"\u003E\u003C/a\u003E（1）demo1\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ListAdd1 {\n\n    private volatile static List list = new ArrayList();\n\n    public void add() {\n        list.add(\"bjsxt\");\n    }\n\n    public int size() {\n        return list.size();\n    }\n\n    public static void main(String[] args) {\n\n        final ListAdd1 list1 = new ListAdd1();\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                try {\n                    for (int i = 0; i \u0026lt; 10; i++) {\n                        list1.add();\n                        System.out.println(\"当前线程：\"\n                                + Thread.currentThread().getName() + \"添加了一个元素..\");\n                        Thread.sleep(500);\n                    }\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }\n        }, \"t1\");\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                while (true) {\n                    if (list1.size() == 5) {\n                        System.out.println(\"当前线程收到通知：\"\n                                + Thread.currentThread().getName() + \" list size = 5 线程停止..\");\n                        throw new RuntimeException();\n                    }\n                }\n            }\n        }, \"t2\");\n\n        t1.start();\n        t2.start();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E线程t2需要一直循环等待，造成浪费\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2demo2\" class=\"anchor\" href=\"#2demo2\"\u003E\u003C/a\u003E（2）demo2\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ListAdd3 {\n\n    private volatile static List list = new ArrayList();\n\n    public void add() {\n        list.add(\"bjsxt\");\n    }\n\n    public int size() {\n        return list.size();\n    }\n\n    public static void main(String[] args) {\n\n        final ListAdd3 listAdd3 = new ListAdd3();\n\n        final Object lock = new Object();\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                synchronized (lock){\n                    for (int i = 0 ; i \u0026lt; 10 ; i++) {\n                        listAdd3.add();\n                        System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"添加了一个元素..\");\n                        try {\n                            Thread.sleep(500);\n                            if (listAdd3.size() == 5) {\n                                System.out.println(\"已经发出通知..\");\n                                lock.notify();  // notify 不释放锁\n                            }\n                        } catch (InterruptedException e) {\n                            e.printStackTrace();\n                        }\n\n                    }\n                }\n            }\n        });\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                synchronized (lock){\n                    if (listAdd3.size() != 5) {\n                        try {\n                            System.out.println(\"t2进入...\");\n                            lock.wait();\n                        } catch (InterruptedException e) {\n                            e.printStackTrace();\n                        }\n                    }\n                    System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"收到通知线程停止..\");\n                    throw new RuntimeException();\n                }\n            }\n        });\n\n        t2.start();\n        t1.start();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E注意：t2一定要先执行\u003C/li\u003E\n\u003Cli\u003Ewait()、notify()必须结合synchronized一起使用\u003C/li\u003E\n\u003Cli\u003Elock.wait() 会释放锁，让t1获取锁\u003C/li\u003E\n\u003Cli\u003Elock.notify() 不释放锁，虽然在通知了，但是线程t2还是无法及时获得锁对象，需等t1执行结束后才获得\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3demo3\" class=\"anchor\" href=\"#3demo3\"\u003E\u003C/a\u003E（3）demo3\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ListAdd4 {\n\n    private volatile static List list = new ArrayList();\n\n    public void add() {\n        list.add(\"bjsxt\");\n    }\n\n    public int size() {\n        return list.size();\n    }\n\n    public static void  main(String[] args) {\n\n        final ListAdd4 listAdd4 = new ListAdd4();\n\n        final CountDownLatch countDownLatch = new CountDownLatch(1);\n\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                for (int i = 0 ; i \u0026lt; 10 ; i++){\n                    listAdd4.add();\n                    System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"添加了一个元素..\");\n                    if (listAdd4.size() == 5) {\n                        System.out.println(\"已经发出通知..\");\n                        countDownLatch.countDown();\n                    }\n                    try {\n                        Thread.sleep(500);\n                    } catch (InterruptedException e) {\n                        e.printStackTrace();\n                    }\n                }\n            }\n        }, \"t1\");\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                if (listAdd4.size() != 5) {\n                    try {\n                        countDownLatch.await();\n                    } catch (InterruptedException e) {\n                        e.printStackTrace();\n                    }\n                }\n\n                System.out.println(\"当前线程：\" + Thread.currentThread().getName() + \"收到通知线程停止..\");\n                throw new RuntimeException();\n            }\n        } , \"t2\");\n\n        t2.start();\n        t1.start();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用CountDownLatch，可以解决demo2中问题，t1一发出通知，t2即可执行\u003C/li\u003E\n\u003C/ul\u003E","697207":"\u003Ch3\u003E\n\u003Ca id=\"1concurrent\" class=\"anchor\" href=\"#1concurrent\"\u003E\u003C/a\u003E1、Concurrent\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class UseConcurrentMap {\n\n\tpublic static void main(String[] args) {\n\t\tConcurrentHashMap\u0026lt;String, Object\u0026gt; chm = new ConcurrentHashMap\u0026lt;String, Object\u0026gt;();\n\t\tchm.put(\"k1\", \"v1\");\n\t\tchm.put(\"k2\", \"v2\");\n\t\tchm.put(\"k3\", \"v3\");\n\t\tchm.putIfAbsent(\"k4\", \"vvvv\");\n\t\t//System.out.println(chm.get(\"k2\"));\n\t\t//System.out.println(chm.size());\n\t\t\n\t\tfor(Map.Entry\u0026lt;String, Object\u0026gt; me : chm.entrySet()){\n\t\t\tSystem.out.println(\"key:\" + me.getKey() + \",value:\" + me.getValue());\n\t\t}\n\t\t\n\t\t\n\t\t\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E将容器分段（最高16段），处理高并发写的\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2copyonwritecow\" class=\"anchor\" href=\"#2copyonwritecow\"\u003E\u003C/a\u003E2.CopyOnWrite（cow）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class UseCopyOnWrite {\n\n\tpublic static void main(String[] args) {\n\t\t\n\t\tCopyOnWriteArrayList\u0026lt;String\u0026gt; cwal = new CopyOnWriteArrayList\u0026lt;String\u0026gt;();\n\t\tCopyOnWriteArraySet\u0026lt;String\u0026gt; cwas = new CopyOnWriteArraySet\u0026lt;String\u0026gt;();\n\t\t\n\t\t\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E处理高并发读，读不加锁\u003C/li\u003E\n\u003Cli\u003E每次写都需要加锁，复制原先的记录，然后进行修改，修改结束后把指针指向新的空间，旧空间释放（垃圾回收）\u003C/li\u003E\n\u003C/ul\u003E","729009":"\u003Ch3\u003E\n\u003Ca id=\"1-创建消息类\" class=\"anchor\" href=\"#1-%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%E7%B1%BB\"\u003E\u003C/a\u003E1. 创建消息类\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 : 消息对象\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class Msg {\n\n    private int id;\n\n    private String name;\n\n    public Msg(int id, String name) {\n        this.id = id;\n        this.name = name;\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    @Override\n    public String toString() {\n        return \"Msg{\" +\n                \"id=\" + id +\n                \", name='\" + name + '\\'' +\n                '}';\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-创建消息生产者\" class=\"anchor\" href=\"#2-%E5%88%9B%E5%BB%BA%E6%B6%88%E6%81%AF%E7%94%9F%E4%BA%A7%E8%80%85\"\u003E\u003C/a\u003E2. 创建消息生产者\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class MsgProvider implements Runnable {\n\n    /**\n     * 消息队列\n     */\n    private BlockingQueue\u0026lt;Msg\u0026gt; queue;\n\n    /**\n     * 是否执行\n     */\n    private boolean isRunning = true;\n\n    /**\n     * 用于生成id\n     */\n    private static AtomicInteger ids = new AtomicInteger(0);\n\n    /**\n     * 用于生成随机数\n     */\n    private Random random = new Random();\n\n\n    @Override\n    public void run() {\n        while (isRunning) {\n            try {\n                // 模拟生产数据浪费时间\n                Thread.sleep(random.nextInt(1000));\n\n                int id = ids.incrementAndGet() ;\n                Msg msg = new Msg(id , \"数据_\" + id) ;\n\n                String threadName = Thread.currentThread().getName() ;\n                if (!queue.offer(msg , 2 , TimeUnit.SECONDS)){\n                    System.out.println(threadName+ \"数据生成识别\");\n                }else {\n                    System.out.println(threadName+ \"数据生成\" + msg);\n                }\n\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n\n    /**\n     * 构造方法，传入消息队列\n     *\n     * @param queue\n     */\n    public MsgProvider(BlockingQueue\u0026lt;Msg\u0026gt; queue) {\n        this.queue = queue;\n    }\n\n\n    /**\n     * 停止执行\n     */\n    public void stop() {\n        this.isRunning = false;\n    }\n\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E注意：ids 必须声明成static才能保证多线程的原子性\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-消息消费者\" class=\"anchor\" href=\"#3-%E6%B6%88%E6%81%AF%E6%B6%88%E8%B4%B9%E8%80%85\"\u003E\u003C/a\u003E3. 消息消费者\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 : 消息消费者\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class MsgConsumer implements Runnable {\n\n    /**\n     * 消息队列\n     */\n    private BlockingQueue\u0026lt;Msg\u0026gt; queue ;\n\n    /**\n     * 是否执行\n     */\n    private boolean isRunning = true ;\n\n    /**\n     * 用于生成随机数\n     */\n    private Random random = new Random();\n\n\n    @Override\n    public void run() {\n        while (isRunning){\n            try {\n                Msg msg = queue.take() ;\n                //进行数据处理。休眠0 - 1000毫秒模拟耗时\n                Thread.sleep(random.nextInt(1000));\n                System.out.println(\"当前消费线程：\" + Thread.currentThread().getName() + \"， 消费成功，消费数据为id: \" + msg);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n        }\n    }\n\n\n    /**\n     * 构造方法，传入消息队列\n     *\n     * @param queue\n     */\n    public MsgConsumer(BlockingQueue\u0026lt;Msg\u0026gt; queue){\n        this.queue = queue ;\n    }\n\n\n    /**\n     * 停止执行\n     */\n    public void stop(){\n        this.isRunning = false ;\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-测试\" class=\"anchor\" href=\"#4-%E6%B5%8B%E8%AF%95\"\u003E\u003C/a\u003E4. 测试\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/6\n */\npublic class MsgMain {\n\n    public static void  main(String[] args) throws Exception {\n\n        // 消息队列\n        BlockingQueue\u0026lt;Msg\u0026gt; queue = new LinkedBlockingDeque\u0026lt;Msg\u0026gt;();\n\n        // 创建消息生产者\n        MsgProvider p1 = new MsgProvider(queue);\n        MsgProvider p2 = new MsgProvider(queue);\n        MsgProvider p3 = new MsgProvider(queue);\n\n\n        // 创建消息消费者\n        MsgConsumer c1 = new MsgConsumer(queue);\n        MsgConsumer c2 = new MsgConsumer(queue);\n        MsgConsumer c3 = new MsgConsumer(queue);\n\n        // 创建线程池，执行线程\n        ExecutorService executorService = Executors.newCachedThreadPool();\n        executorService.execute(p1);\n        executorService.execute(p2);\n        executorService.execute(p3);\n\n        executorService.execute(c1);\n        executorService.execute(c2);\n        executorService.execute(c3);\n\n        // 休眠3s后停止生产\n        Thread.sleep(3000);\n        p1.stop();\n        p2.stop();\n        p3.stop();\n\n        // 休眠3s后停止消费\n        Thread.sleep(3000);\n        c1.stop();\n        c2.stop();\n        c3.stop();\n\n        executorService.shutdown();\n\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E","736283":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.util.Random;\nimport java.util.concurrent.CountDownLatch;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 : 测试CountDownLatch\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/10\n */\npublic class TestCountDownLatch {\n\n\n    public static void main(String[] args) {\n\n        final CountDownLatch countDownLatch = new CountDownLatch(2);\n\n        /**\n         * 主线程\n         */\n        new Thread(() -\u0026gt; {\n            try {\n                // 进入等待\n                countDownLatch.await();\n                System.out.println(\"所有线程都执行完毕....\");\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n\n        }).start();\n\n\n        for (int i = 0; i \u0026lt; 2; i++) {\n            final int t = i;\n            new Thread(() -\u0026gt; {\n                try {\n                    System.out.println(\"线程\" + t + \"开始....\");\n                    Thread.sleep(new Random().nextInt(2000));\n                    // 进行计数\n                    countDownLatch.countDown();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }).start();\n        }\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0910/103119_6066e67e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ECountDownLatch是在java1.5被引入的，它存在于java.util.concurrent包下。\u003C/li\u003E\n\u003Cli\u003ECountDownLatch这个类能够使一个线程等待其他线程完成各自的工作后再执行\u003C/li\u003E\n\u003Cli\u003ECountDownLatch是通过一个计数器来实现的，计数器的初始值为线程的数量。每当一个线程完成了自己的任务后，计数器的值就会减1。当计数器值到达0时，它表示所有的线程已经完成了任务，然后在闭锁上等待的线程就可以恢复执行任务\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0910/100926_10734d14_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-使用场景\" class=\"anchor\" href=\"#3-%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF\"\u003E\u003C/a\u003E3. 使用场景\u003C/h3\u003E\n\u003Cp\u003E（1）实现最大的并行性：有时我们想同时启动多个线程，实现最大程度的并行性。例如，我们想测试一个单例类。如果我们创建一个初始计数为1的CountDownLatch，并让所有线程都在这个锁上等待，那么我们可以很轻松地完成测试。我们只需调用 一次countDown()方法就可以让所有的等待线程同时恢复执行。\u003C/p\u003E\n\u003Cp\u003E（2）开始执行前等待n个线程完成各自任务：例如应用程序启动类要确保在处理用户请求前，所有N个外部系统已经启动和运行了。\u003C/p\u003E\n\u003Cp\u003E（3）死锁检测：一个非常方便的使用场景是，你可以使用n个线程访问共享资源，在每次测试阶段的线程数目是不同的，并尝试产生死锁。\u003C/p\u003E","798468":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/25\n */\npublic class TestReentranLock {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n\n    /**\n     * 定义锁\n     */\n    private Lock lock = new ReentrantLock();\n\n\n    /**\n     * 执行方法\n     */\n    public void m1() {\n        try {\n            lock.lock();\n            System.out.println(FORMAT.format(new Date()) + Thread.currentThread().getName() + \"--\u0026gt; m1 开始\");\n            Thread.sleep(1000);\n            System.out.println(FORMAT.format(new Date()) + Thread.currentThread().getName() + \"--\u0026gt; m1 结束\");\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n    public static void main(String[] args) {\n        final TestReentranLock test = new TestReentranLock();\n        /**\n         * 多线程执行，需要等上一线程执行完成，下一个线程才能开始\n         */\n        for (int i = 0; i \u0026lt; 3; i++) {\n            new Thread(() -\u0026gt; {\n                test.m1();\n            }, \"线程 t\" + i).start();\n        }\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0925/175700_9b2465da_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E多线程执行，需要等上一线程执行完成，下一个线程才能开始\u003C/li\u003E\n\u003Cli\u003E结合try...catch...finally 使用\u003C/li\u003E\n\u003C/ul\u003E","987022":"\u003Ch3\u003E\n\u003Ca id=\"1-安装准备\" class=\"anchor\" href=\"#1-%E5%AE%89%E8%A3%85%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E1. 安装准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E首先从官网上下载\u003Ca href=\"https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html\"\u003EJdk 8下载\u003C/a\u003E\n\u003C/li\u003E\n\u003Cli\u003E检查系统自带JDK\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Erpm -qa | grep java\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E卸载系统自带open jdk\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Erpm -e –-nodeps XXXX_openjdk_XXX \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E以上两步可以和在一起操作\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Erpm -e --nodeps `rpm -qa | grep java`\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-jdk的安装\" class=\"anchor\" href=\"#2-jdk%E7%9A%84%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. Jdk的安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压jdk压缩包\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar –xzvf jdk-8u45-linux-x64.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压后的jdk的文件夹名字为jdk1.8.0_45,我们把它改为jdk1.8\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Emv jdk1.8.0_45/ jdk1.8/\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-jdk的配置\" class=\"anchor\" href=\"#3-jdk%E7%9A%84%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3. jdk的配置\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用vim命令打开系统的环境变量配置文件：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evi /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在profile文件最后加入：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E## JAVA\n\nexport JAVA_HOME=/usr/local/deve/soft/jdk1.8\n\nexport PATH=$PATH:$JAVA_HOME/bin\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置文件立即生效\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esource /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-配置验证\" class=\"anchor\" href=\"#4-%E9%85%8D%E7%BD%AE%E9%AA%8C%E8%AF%81\"\u003E\u003C/a\u003E4. 配置验证\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E输入java –version，会得到：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003Ejava version \"1.8.0_45\"\u003C/p\u003E\n\u003Cp\u003EJava(TM) SE Runtime Environment (build 1.8.0_45-b14)\u003C/p\u003E\n\u003Cp\u003EJava HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)\u003C/p\u003E","987032":"\u003Ch3\u003E\n\u003Ca id=\"centos7修改时区的正确姿势\" class=\"anchor\" href=\"#centos7%E4%BF%AE%E6%94%B9%E6%97%B6%E5%8C%BA%E7%9A%84%E6%AD%A3%E7%A1%AE%E5%A7%BF%E5%8A%BF\"\u003E\u003C/a\u003ECentOS7修改时区的正确姿势\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"检查\" class=\"anchor\" href=\"#%E6%A3%80%E6%9F%A5\"\u003E\u003C/a\u003E检查\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Edate\n\u003C/code\u003E\u003C/pre\u003E","987038":"\u003Ch3\u003E\n\u003Ca id=\"1-vi的基本概念\" class=\"anchor\" href=\"#1-vi%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5\"\u003E\u003C/a\u003E1. vi的基本概念\u003C/h3\u003E\n\u003Cp\u003E　　基本上vi可以分为三种状态，分别是命令模式（command mode）、插入模式（Insert mode）和底行模式（last line mode），各模式的功能区分如下：\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E1) 命令行模式command mode）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E　　控制屏幕光标的移动，字符、字或行的删除，移动复制某区段及进入Insert mode下，或者到 last line mode。\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E2) 插入模式（Insert mode）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E　　只有在Insert mode下，才可以做文字输入，按「ESC」键可回到命令行模式。\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E3) 底行模式（last line mode）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E　　将文件保存或退出vi，也可以设置编辑环境，如寻找字符串、列出行号……等。\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E不过一般我们在使用时把vi简化成两个模式，就是将底行模式（last line mode）也算入命令行模式command mode）。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-修改vim配置信息\" class=\"anchor\" href=\"#2-%E4%BF%AE%E6%94%B9vim%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E2. 修改vim配置信息\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改用户配置信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim ~/.vimrc  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改全局配置信息\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/vimrc\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-可配置信息\" class=\"anchor\" href=\"#3-%E5%8F%AF%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E3. 可配置信息\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eall：列出所有选项设置情况 \nterm：设置终端类型 \nignorance：在搜索中忽略大小写 \nlist：显示制表位(Ctrl+I)和行尾标志（$) \nnumber：显示行号 \nreport：显示由面向行的命令修改过的数目 \nterse：显示简短的警告信息 \nwarn：在转到别的文件时若没保存当前文件则显示NO write信息 \nnomagic：允许在搜索模式中，使用前面不带“\\”的特殊字符 \nnowrapscan：禁止vi在搜索到达文件两端时，又从另一端开始 \nmesg：允许vi显示其他用户用write写到自己终端上的信息\n\u003C/code\u003E\u003C/pre\u003E","987039":"\u003Ch3\u003E\n\u003Ca id=\"1-进入vi的命令\" class=\"anchor\" href=\"#1-%E8%BF%9B%E5%85%A5vi%E7%9A%84%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 进入vi的命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi filename\u003C/td\u003E\n\u003Ctd\u003E打开或新建文件，并将光标置于第一行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi +n filename\u003C/td\u003E\n\u003Ctd\u003E打开文件，并将光标置于第n行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi + filename\u003C/td\u003E\n\u003Ctd\u003E打开文件，并将光标置于最后一行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi +/pattern filename\u003C/td\u003E\n\u003Ctd\u003E打开文件，并将光标置于第一个与pattern匹配的串处\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi -r filename\u003C/td\u003E\n\u003Ctd\u003E在上次正用vi编辑时发生系统崩溃，恢复filename\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Evi filename....filename\u003C/td\u003E\n\u003Ctd\u003E打开多个文件，依次进行编辑\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","987040":"\u003Ch3\u003E\n\u003Ca id=\"1-移动光标类命令\" class=\"anchor\" href=\"#1-%E7%A7%BB%E5%8A%A8%E5%85%89%E6%A0%87%E7%B1%BB%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 移动光标类命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eh\u003C/td\u003E\n\u003Ctd\u003E光标左移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003El\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Espace\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EBackspace\u003C/td\u003E\n\u003Ctd\u003E光标左移一个字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ek或Ctrl+p\u003C/td\u003E\n\u003Ctd\u003E光标上移一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ej或Ctrl+n\u003C/td\u003E\n\u003Ctd\u003E光标下移一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EEnter\u003C/td\u003E\n\u003Ctd\u003E光标下移一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ew或W\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字至字首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eb或B\u003C/td\u003E\n\u003Ctd\u003E光标左移一个字至字首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ee或E\u003C/td\u003E\n\u003Ctd\u003E光标右移一个字至字尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E)\u003C/td\u003E\n\u003Ctd\u003E光标移至句尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E(\u003C/td\u003E\n\u003Ctd\u003E光标移至句首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E}\u003C/td\u003E\n\u003Ctd\u003E光标移至段落开头\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E{\u003C/td\u003E\n\u003Ctd\u003E光标移至段落结尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EnG\u003C/td\u003E\n\u003Ctd\u003E光标移至第n行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En+\u003C/td\u003E\n\u003Ctd\u003E光标下移n行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En-\u003C/td\u003E\n\u003Ctd\u003E光标上移n行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En$\u003C/td\u003E\n\u003Ctd\u003E光标移至第n行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EH\u003C/td\u003E\n\u003Ctd\u003E光标移至屏幕顶行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EM\u003C/td\u003E\n\u003Ctd\u003E光标移至屏幕中间行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EL\u003C/td\u003E\n\u003Ctd\u003E光标移至屏幕最后行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E0\u003C/td\u003E\n\u003Ctd\u003E（注意是数字零）光标移至当前行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E$\u003C/td\u003E\n\u003Ctd\u003E光标移至当前行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","987041":"\u003Ch3\u003E\n\u003Ca id=\"1-屏幕翻滚类命令\" class=\"anchor\" href=\"#1-%E5%B1%8F%E5%B9%95%E7%BF%BB%E6%BB%9A%E7%B1%BB%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 屏幕翻滚类命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+u\u003C/td\u003E\n\u003Ctd\u003E向文件首翻半屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+d\u003C/td\u003E\n\u003Ctd\u003E向文件尾翻半屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+f\u003C/td\u003E\n\u003Ctd\u003E向文件尾翻一屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl＋b\u003C/td\u003E\n\u003Ctd\u003E向文件首翻一屏\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Enz\u003C/td\u003E\n\u003Ctd\u003E将第n行滚至屏幕顶部，不指定n时将当前行滚至屏幕顶部。\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","987042":"\u003Ch3\u003E\n\u003Ca id=\"1-插入文本类命令\" class=\"anchor\" href=\"#1-%E6%8F%92%E5%85%A5%E6%96%87%E6%9C%AC%E7%B1%BB%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 插入文本类命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ei\u003C/td\u003E\n\u003Ctd\u003E在光标前\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EI\u003C/td\u003E\n\u003Ctd\u003E在当前行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ea\u003C/td\u003E\n\u003Ctd\u003E光标后\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EA\u003C/td\u003E\n\u003Ctd\u003E在当前行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eo\u003C/td\u003E\n\u003Ctd\u003E在当前行之下新开一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EO\u003C/td\u003E\n\u003Ctd\u003E在当前行之上新开一行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Er\u003C/td\u003E\n\u003Ctd\u003E替换当前字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ER\u003C/td\u003E\n\u003Ctd\u003E替换当前字符及其后的字符，直至按ESC键\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Es\u003C/td\u003E\n\u003Ctd\u003E从当前光标位置处开始，以输入的文本替代指定数目的字符\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ES\u003C/td\u003E\n\u003Ctd\u003E删除指定数目的行，并以所输入文本代替之\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Encw或nCW\u003C/td\u003E\n\u003Ctd\u003E修改指定数目的字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EnCC\u003C/td\u003E\n\u003Ctd\u003E修改指定数目的行\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","987043":"\u003Ch3\u003E\n\u003Ca id=\"删除命令\" class=\"anchor\" href=\"#%E5%88%A0%E9%99%A4%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E删除命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Endw或ndW\u003C/td\u003E\n\u003Ctd\u003E删除光标处开始及其后的n-1个字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ed0\u003C/td\u003E\n\u003Ctd\u003E删至行首\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ed$\u003C/td\u003E\n\u003Ctd\u003E删至行尾\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Endd\u003C/td\u003E\n\u003Ctd\u003E删除当前行及其后n-1行\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ex或X\u003C/td\u003E\n\u003Ctd\u003E删除一个字符，x删除光标后的，而X删除光标前的\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003ECtrl+u\u003C/td\u003E\n\u003Ctd\u003E删除输入方式下所输入的文本\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","987044":"\u003Ch3\u003E\n\u003Ca id=\"1-搜索及替换命令\" class=\"anchor\" href=\"#1-%E6%90%9C%E7%B4%A2%E5%8F%8A%E6%9B%BF%E6%8D%A2%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 搜索及替换命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E/pattern\u003C/td\u003E\n\u003Ctd\u003E从光标开始处向文件尾搜索pattern\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E?pattern\u003C/td\u003E\n\u003Ctd\u003E从光标开始处向文件首搜索pattern\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003En\u003C/td\u003E\n\u003Ctd\u003E在同一方向重复上一次搜索命令\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003EN\u003C/td\u003E\n\u003Ctd\u003E在反方向上重复上一次搜索命令\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:s/p1/p2/g\u003C/td\u003E\n\u003Ctd\u003E将当前行中所有p1均用p2替代\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:%s/p1/p2/g\u003C/td\u003E\n\u003Ctd\u003E将所有p1均用p2替代\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2s/p1/p2/g\u003C/td\u003E\n\u003Ctd\u003E将第n1至n2行中所有p1均用p2替代\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:g/p1/s//p2/g\u003C/td\u003E\n\u003Ctd\u003E将文件中所有p1均用p2替换\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:%s+/str11/str12/+/str21/str22+\u003C/td\u003E\n\u003Ctd\u003E（使用+ 来 替换 / ）： /str11/str12/替换成/str21/str22/\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-替换demo\" class=\"anchor\" href=\"#2-%E6%9B%BF%E6%8D%A2demo\"\u003E\u003C/a\u003E2. 替换demo\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E将 /usr/local/deve/soft/redis 替换成 /usr/local/redis\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E%s+/deve/soft/+/+g  \n\u003C/code\u003E\u003C/pre\u003E","987045":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 co n3\u003C/td\u003E\n\u003Ctd\u003E将n1行到n2行之间的内容拷贝到第n3行下\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 m n3\u003C/td\u003E\n\u003Ctd\u003E将n1行到n2行之间的内容移至到第n3行下\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 d\u003C/td\u003E\n\u003Ctd\u003E将n1行到n2行之间的内容删除\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:w\u003C/td\u003E\n\u003Ctd\u003E保存当前文件\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:e filename\u003C/td\u003E\n\u003Ctd\u003E打开文件filename进行编辑\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:x\u003C/td\u003E\n\u003Ctd\u003E保存当前文件并退出\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:q\u003C/td\u003E\n\u003Ctd\u003E退出vi\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:q!\u003C/td\u003E\n\u003Ctd\u003E不保存文件并退出vi\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:!command\u003C/td\u003E\n\u003Ctd\u003E执行shell命令command\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:n1,n2 w!command\u003C/td\u003E\n\u003Ctd\u003E将文件中n1行至n2行的内容作为command的输入并执行之，若不指定n1，n2，则表示将整个文件内容作为command的输入\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E:r!command\u003C/td\u003E\n\u003Ctd\u003E将命令command的输出结果放到当前行\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","987046":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?nyy\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下n行的内容保存到寄存器？中，其中?为一个字母，n为一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?nyw\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下n个字保存到寄存器？中，其中?为一个字母，n为一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?nyl\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下n个字符保存到寄存器？中，其中?为一个字母，n为一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E\"?p\u003C/td\u003E\n\u003Ctd\u003E取出寄存器？中的内容并将其放到光标位置处。这里？可以是一个字母，也可以是一个数字\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Endd\u003C/td\u003E\n\u003Ctd\u003E将当前行及其下共n行文本删除，并将所删内容放到1号删除寄存器中。\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","987048":"\u003Col class=\"task-list\"\u003E\n\u003Cli\u003E创建用户\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E//创建monitor用户，用户id为501，所属组为monitor，附加群组为admin，起始目录为/monitor\nuseradd -u 501 -g monitor -G admin -d /monitor monitor\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-u:直接给出userID\u003C/li\u003E\n\u003Cli\u003E-g:指定用户所属的群组\u003C/li\u003E\n\u003Cli\u003E-G 指定用户所属的附加群组\u003C/li\u003E\n\u003Cli\u003E-d:指定用户登入时的启始目录\u003C/li\u003E\n\u003Cli\u003E-s:定义shell\u003C/li\u003E\n\u003C/ul\u003E\n\u003Col start=\"2\" class=\"task-list\"\u003E\n\u003Cli\u003E设置密码：\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003Epasswd fxz\n\n或者\n\necho \"123456\" | passwd --stdin fxz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"3\" class=\"task-list\"\u003E\n\u003Cli\u003E用户信息文件\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecat /etc/passwd\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"4\" class=\"task-list\"\u003E\n\u003Cli\u003E用户密码文件\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E/etc/shadow\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"5\" class=\"task-list\"\u003E\n\u003Cli\u003E用户组文件\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecat /etc/group\n\u003C/code\u003E\u003C/pre\u003E","987051":"\u003Ch3\u003E\n\u003Ca id=\"1将文件checkout到本地目录\" class=\"anchor\" href=\"#1%E5%B0%86%E6%96%87%E4%BB%B6checkout%E5%88%B0%E6%9C%AC%E5%9C%B0%E7%9B%AE%E5%BD%95\"\u003E\u003C/a\u003E1.将文件checkout到本地目录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn checkout path（path是服务器上的目录）\n例如：svn checkout svn://192.168.1.1/pro/domain\n简写：svn co\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2往版本库中添加新的文件\" class=\"anchor\" href=\"#2%E5%BE%80%E7%89%88%E6%9C%AC%E5%BA%93%E4%B8%AD%E6%B7%BB%E5%8A%A0%E6%96%B0%E7%9A%84%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E2.往版本库中添加新的文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn add file\n例如：svn add test.php(添加test.php)\nsvn add *.php(添加当前目录下所有的php文件)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3将改动的文件提交到版本库\" class=\"anchor\" href=\"#3%E5%B0%86%E6%94%B9%E5%8A%A8%E7%9A%84%E6%96%87%E4%BB%B6%E6%8F%90%E4%BA%A4%E5%88%B0%E7%89%88%E6%9C%AC%E5%BA%93\"\u003E\u003C/a\u003E3.将改动的文件提交到版本库\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn commit -m \"LogMessage\" [-N] [--no-unlock] PATH(如果选择了保持锁，就使用--no-unlock开关)\n例如：svn commit -m \"add test file for my test\" test.php\n简写：svn ci\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4加锁解锁\" class=\"anchor\" href=\"#4%E5%8A%A0%E9%94%81%E8%A7%A3%E9%94%81\"\u003E\u003C/a\u003E4.加锁/解锁\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn lock -m \"LockMessage\" [--force] PATH\n例如：svn lock -m \"lock test file\" test.php\nsvn unlock PATH\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5更新到某个版本\" class=\"anchor\" href=\"#5%E6%9B%B4%E6%96%B0%E5%88%B0%E6%9F%90%E4%B8%AA%E7%89%88%E6%9C%AC\"\u003E\u003C/a\u003E5.更新到某个版本\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn update -r m path\n例如：\nsvn update如果后面没有目录，默认将当前目录以及子目录下的所有文件都更新到最新版本。\nsvn update -r 200 test.php(将版本库中的文件test.php还原到版本200)\nsvn update test.php(更新，于版本库同步。如果在提交的时候提示过期的话，是因为冲突，需要先update，修改文件，然后清除svn resolved，最后再提交commit)\n简写：svn up\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6查看文件或者目录状态\" class=\"anchor\" href=\"#6%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6%E6%88%96%E8%80%85%E7%9B%AE%E5%BD%95%E7%8A%B6%E6%80%81\"\u003E\u003C/a\u003E6.查看文件或者目录状态\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1）svn status path（目录下的文件和子目录的状态，正常状态不显示）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E【?：不在svn的控制中；M：内容被修改；C：发生冲突；A：预定加入到版本库；K：被锁定】\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E2）svn status -v path(显示文件和子目录状态)\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E第一列保持相同，第二列显示工作版本号，第三和第四列显示最后一次修改的版本号和修改人。\n注：svn status.svn diff和 svn revert这三条命令在没有网络的情况下也可以执行的，原因是svn在本地的.svn中保留了本地版本的原始拷贝。\n简写：svn st\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"7删除文件\" class=\"anchor\" href=\"#7%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E7.删除文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn delete path -m \"delete test fle\"\n例如：svn delete svn://192.168.1.1/pro/domain/test.php -m \"delete test file\"\n或者直接svn delete test.php 然后再svn ci -m 'delete test file‘，推荐使用这种\n简写：svn (del, remove, rm)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"8查看日志\" class=\"anchor\" href=\"#8%E6%9F%A5%E7%9C%8B%E6%97%A5%E5%BF%97\"\u003E\u003C/a\u003E8.查看日志\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn log path\n例如：svn log test.php 显示这个文件的所有修改记录，及其版本号的变化\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"9查看文件详细信息\" class=\"anchor\" href=\"#9%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6%E8%AF%A6%E7%BB%86%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E9.查看文件详细信息\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn info path\n例如：svn info test.php\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"10比较差异\" class=\"anchor\" href=\"#10%E6%AF%94%E8%BE%83%E5%B7%AE%E5%BC%82\"\u003E\u003C/a\u003E10.比较差异\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn diff path(将修改的文件与基础版本比较)\n例如：svn diff test.php\nsvn diff -r m:n path(对版本m和版本n比较差异)\n例如：svn diff -r 200:201 test.php\n简写：svn di\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"11将两个版本之间的差异合并到当前文件\" class=\"anchor\" href=\"#11%E5%B0%86%E4%B8%A4%E4%B8%AA%E7%89%88%E6%9C%AC%E4%B9%8B%E9%97%B4%E7%9A%84%E5%B7%AE%E5%BC%82%E5%90%88%E5%B9%B6%E5%88%B0%E5%BD%93%E5%89%8D%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E11.将两个版本之间的差异合并到当前文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn merge -r m:n path\n例如：svn merge -r 200:205 test.php（将版本200与205之间的差异合并到当前文件，但是一般都会产生冲突，需要处理一下）\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"12svn-帮助\" class=\"anchor\" href=\"#12svn-%E5%B8%AE%E5%8A%A9\"\u003E\u003C/a\u003E12.SVN 帮助\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn help\nsvn help ci\n\u003C/code\u003E\u003C/pre\u003E\n\u003Chr\u003E\n\u003Cp\u003E以上是常用命令，下面写几个不经常用的\u003C/p\u003E\n\u003Chr\u003E\n\u003Ch3\u003E\n\u003Ca id=\"13版本库下的文件和目录列表\" class=\"anchor\" href=\"#13%E7%89%88%E6%9C%AC%E5%BA%93%E4%B8%8B%E7%9A%84%E6%96%87%E4%BB%B6%E5%92%8C%E7%9B%AE%E5%BD%95%E5%88%97%E8%A1%A8\"\u003E\u003C/a\u003E13.版本库下的文件和目录列表\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn list path\n显示path目录下的所有属于版本库的文件和目录\n简写：svn ls\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"14创建纳入版本控制下的新目录\" class=\"anchor\" href=\"#14%E5%88%9B%E5%BB%BA%E7%BA%B3%E5%85%A5%E7%89%88%E6%9C%AC%E6%8E%A7%E5%88%B6%E4%B8%8B%E7%9A%84%E6%96%B0%E7%9B%AE%E5%BD%95\"\u003E\u003C/a\u003E14.创建纳入版本控制下的新目录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn mkdir: 创建纳入版本控制下的新目录。\n用法: 1.mkdir PATH...\n 2.mkdir URL...\n创建版本控制的目录。\n1.每一个以工作副本 PATH 指定的目录，都会创建在本地端，并且加入新增\n调度，以待下一次的提交。\n2.每个以URL指定的目录，都会透过立即提交于仓库中创建。\n在这两个情况下，所有的中间目录都必须事先存在。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"15恢复本地修改\" class=\"anchor\" href=\"#15%E6%81%A2%E5%A4%8D%E6%9C%AC%E5%9C%B0%E4%BF%AE%E6%94%B9\"\u003E\u003C/a\u003E15.恢复本地修改\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn revert: 恢复原始未改变的工作副本文件 (恢复大部份的本地修改)。revert:\n用法: revert PATH...\n注意: 本子命令不会存取网络，并且会解除冲突的状况。但是它不会恢复\n被删除的目录\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"16代码库url变更\" class=\"anchor\" href=\"#16%E4%BB%A3%E7%A0%81%E5%BA%93url%E5%8F%98%E6%9B%B4\"\u003E\u003C/a\u003E16.代码库URL变更\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn switch (sw): 更新工作副本至不同的URL。\n用法: 1.switch URL [PATH]\n2.switch --relocate FROM TO [PATH...]\n\n1.更新你的工作副本，映射到一个新的URL，其行为跟“svn update”很像，也会将\n服务器上文件与本地文件合并。这是将工作副本对应到同一仓库中某个分支或者标记的\n方法。\n2.改写工作副本的URL元数据，以反映单纯的URL上的改变。当仓库的根URL变动 \n(比如方案名或是主机名称变动)，但是工作副本仍旧对映到同一仓库的同一目录时使用\n这个命令更新工作副本与仓库的对应关系。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"17解决冲突\" class=\"anchor\" href=\"#17%E8%A7%A3%E5%86%B3%E5%86%B2%E7%AA%81\"\u003E\u003C/a\u003E17.解决冲突\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn resolved: 移除工作副本的目录或文件的“冲突”状态。\n用法: resolved PATH...\n注意: 本子命令不会依语法来解决冲突或是移除冲突标记；它只是移除冲突的\n相关文件，然后让 PATH 可以再次提交。\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"18输出指定文件或url的内容\" class=\"anchor\" href=\"#18%E8%BE%93%E5%87%BA%E6%8C%87%E5%AE%9A%E6%96%87%E4%BB%B6%E6%88%96url%E7%9A%84%E5%86%85%E5%AE%B9\"\u003E\u003C/a\u003E18.输出指定文件或URL的内容。\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esvn cat 目标[@版本]...如果指定了版本，将从指定的版本开始查找。\nsvn cat -r PREV filename \u0026gt; filename (PREV 是上一版本,也可以写具体版本号,这样输出结果是可以提交的)\n\u003C/code\u003E\u003C/pre\u003E","987052":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E备注\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003El\u003C/td\u003E\n\u003Ctd\u003E长格式输出；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eu\u003C/td\u003E\n\u003Ctd\u003E按用户名和启动时间的顺序来显示进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ej\u003C/td\u003E\n\u003Ctd\u003E用任务格式来显示进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ef\u003C/td\u003E\n\u003Ctd\u003E用树形格式来显示进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ea\u003C/td\u003E\n\u003Ctd\u003E显示所有用户的所有进程（包括其它用户）；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ex\u003C/td\u003E\n\u003Ctd\u003E显示无控制终端的进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Er\u003C/td\u003E\n\u003Ctd\u003E显示运行中的进程；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Eww\u003C/td\u003E\n\u003Ctd\u003E避免详细参数被截断；\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-A\u003C/td\u003E\n\u003Ctd\u003E列出所有的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-w\u003C/td\u003E\n\u003Ctd\u003E显示加宽可以显示较多的资讯\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-au\u003C/td\u003E\n\u003Ctd\u003E显示较详细的资讯\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-aux\u003C/td\u003E\n\u003Ctd\u003E显示所有包含其他使用者的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-e\u003C/td\u003E\n\u003Ctd\u003E显示所有进程,环境变量\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-f\u003C/td\u003E\n\u003Ctd\u003E全格式\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-h\u003C/td\u003E\n\u003Ctd\u003E不显示标题\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-l\u003C/td\u003E\n\u003Ctd\u003E长格式\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-w\u003C/td\u003E\n\u003Ctd\u003E宽输出\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ea\u003C/td\u003E\n\u003Ctd\u003E显示终端上地所有进程,包括其他用户的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Er\u003C/td\u003E\n\u003Ctd\u003E只显示正在运行的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ex\u003C/td\u003E\n\u003Ctd\u003E显示没有控制终端的进程\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E我们常用的选项是组合是 aux 或 lax，还有参数 f 的应用。\u003C/li\u003E\n\u003C/ul\u003E","987054":"\u003Ch3\u003E\n\u003Ca id=\"1-demoxlauchcom\" class=\"anchor\" href=\"#1-demoxlauchcom\"\u003E\u003C/a\u003E1. demo.xlauch.com\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/project/xlauch-web\u003C/li\u003E\n\u003Cli\u003Eredis启动命令：service redis start\u003C/li\u003E\n\u003Cli\u003Etomcat目录：/usr/soft/apache-tomcat-7.0.68\u003C/li\u003E\n\u003Cli\u003E启动命令：./startup.sh\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2wangmarket-建站系统\" class=\"anchor\" href=\"#2wangmarket-%E5%BB%BA%E7%AB%99%E7%B3%BB%E7%BB%9F\"\u003E\u003C/a\u003E2.wangmarket 建站系统\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/project/web-market\u003C/li\u003E\n\u003Cli\u003Etomcat目录：/usr/soft/apache-tomcat-8.5.31\u003C/li\u003E\n\u003Cli\u003E启动命令：./startup.sh\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3frp\" class=\"anchor\" href=\"#3frp\"\u003E\u003C/a\u003E3.frp\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/local/frp_0.17.0_linux_amd64/\u003C/li\u003E\n\u003Cli\u003E启动命令：setsid ./frps -c frps.ini\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4nginx\" class=\"anchor\" href=\"#4nginx\"\u003E\u003C/a\u003E4.Nginx\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/etc/nginx/\u003C/li\u003E\n\u003Cli\u003E启动命令：service nginx start\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5erueka-server\" class=\"anchor\" href=\"#5erueka-server\"\u003E\u003C/a\u003E5.erueka-server\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E工程目录：/etc/nginx/\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E启动命令：\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Enohup java -jar eurekaserver-0.0.1-SNAPSHOT.jar --spring.profiles.active=9081 \u0026gt;\u0026gt; /usr/project/logs/eureka/9081 .log 2\u0026gt;\u0026amp;1 \u0026amp;\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Enohup java -jar eurekaserver-0.0.1-SNAPSHOT.jar --spring.profiles.active=9082 \u0026gt;\u0026gt; /usr/project/logs/eureka/9082.log 2\u0026gt;\u0026amp;1 \u0026amp;\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6gogs\" class=\"anchor\" href=\"#6gogs\"\u003E\u003C/a\u003E6.gogs\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E工程目录：/usr/local/gogs/\u003C/li\u003E\n\u003Cli\u003E启动命令：nohup ./gogs web \u0026amp;\u003C/li\u003E\n\u003C/ul\u003E","995807":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://blog.csdn.net/bruce128/article/details/79357870\"\u003EJDK1.8 JVM运行时数据区域划分\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-结构图\" class=\"anchor\" href=\"#2-%E7%BB%93%E6%9E%84%E5%9B%BE\"\u003E\u003C/a\u003E2. 结构图\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1115/103136_453d4438_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"21-类加载子系统\" class=\"anchor\" href=\"#21-%E7%B1%BB%E5%8A%A0%E8%BD%BD%E5%AD%90%E7%B3%BB%E7%BB%9F\"\u003E\u003C/a\u003E2.1. 类加载子系统\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E负责从文件或者网络中加载class信息，加载的信息存放在方法区\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"22-方法区\" class=\"anchor\" href=\"#22-%E6%96%B9%E6%B3%95%E5%8C%BA\"\u003E\u003C/a\u003E2.2. 方法区\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E存放类信息、常量信息、常量池信息、包括字符串字常量和数字常量\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"23-java堆\" class=\"anchor\" href=\"#23-java%E5%A0%86\"\u003E\u003C/a\u003E2.3. JAVA堆\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ejava程序最主要的内存工作区域，几乎所有的对象实例都存在java堆中，堆空间是所有线程共享\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"24-直接内存\" class=\"anchor\" href=\"#24-%E7%9B%B4%E6%8E%A5%E5%86%85%E5%AD%98\"\u003E\u003C/a\u003E2.4. 直接内存\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ejava的NIO库允许java程序使用直接内存，从而提高性能，通常直接内存速度会优于java堆。读写频繁的场合可能会考虑使用\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"25-java栈\" class=\"anchor\" href=\"#25-java%E6%A0%88\"\u003E\u003C/a\u003E2.5. JAVA栈\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E每个虚拟机线程都有一个私有的栈，用于保存局部变量、方法参数、方法调用的返回值等\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"26-本地方法栈\" class=\"anchor\" href=\"#26-%E6%9C%AC%E5%9C%B0%E6%96%B9%E6%B3%95%E6%A0%88\"\u003E\u003C/a\u003E2.6. 本地方法栈\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E用于本地方法调用（通常使用C编写）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"27-pc寄存器\" class=\"anchor\" href=\"#27-pc%E5%AF%84%E5%AD%98%E5%99%A8\"\u003E\u003C/a\u003E2.7. PC寄存器\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E每个线程私有空间，用于存放当前执行环境指针、程序计数器、操作栈指针\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"28-gc垃圾回收\" class=\"anchor\" href=\"#28-gc%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6\"\u003E\u003C/a\u003E2.8. GC垃圾回收\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E开发人员无需手工清理\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"29-执行引擎\" class=\"anchor\" href=\"#29-%E6%89%A7%E8%A1%8C%E5%BC%95%E6%93%8E\"\u003E\u003C/a\u003E2.9. 执行引擎\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E负责执行虚拟机的字节码，一般用户先进行编译成机器码后执行\u003C/li\u003E\n\u003C/ul\u003E","1164286":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://blog.csdn.net/gary_yan/article/details/77981303\"\u003Ehttps的SSL证书在服务器端的部署\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-tomcat下配置\" class=\"anchor\" href=\"#2-tomcat%E4%B8%8B%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E2. tomcat下配置\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Connector port=\"18443\"\n\t\tprotocol=\"HTTP/1.1\"\n\t\tSSLEnabled=\"true\"\n\t\tscheme=\"https\"\n\t\tsecure=\"true\"\n\t\tkeystoreFile=\"E:/deve/tools/apache-tomcat-8.5.31/cert/cert-1541639405263_fxz.xlauch.com.pfx\"\n\t\tkeystoreType=\"PKCS12\"\n\t\tkeystorePass=\"FWhJH4TX\"\n\t\tclientAuth=\"false\"\n\t\tSSLProtocol=\"TLSv1+TLSv1.1+TLSv1.2\"\n\t\tciphers=\"TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256\"/\u0026gt;\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-springboot-配置\" class=\"anchor\" href=\"#3-springboot-%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3. springboot 配置\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eserver.port = 18443 \n\nserver.ssl.key-store=classpath:cert-1541639405263_fxz.xlauch.com.pfx\nserver.ssl.key-store-password=FWhJH4TX\nserver.ssl.keyStoreType=PKCS12\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1219/105753_6c6c1f2a_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","1340230":"\u003Cp\u003E官网地址：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"http://dubbo.apache.org/zh-cn/\"\u003Ehttp://dubbo.apache.org/zh-cn/\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003Egit 地址：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://github.com/apache/incubator-dubbo-spring-boot-project/blob/master/README_CN.md\"\u003Ehttps://github.com/apache/incubator-dubbo-spring-boot-project/blob/master/README_CN.md\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1-创建demo工程\" class=\"anchor\" href=\"#1-%E5%88%9B%E5%BB%BAdemo%E5%B7%A5%E7%A8%8B\"\u003E\u003C/a\u003E1. 创建demo工程\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E目录结构如下：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2019/0227/152222_ab951636_907621.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Epom.xml 配置版本信息：\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n\u0026lt;project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u0026gt;\n    \u0026lt;modelVersion\u0026gt;4.0.0\u0026lt;/modelVersion\u0026gt;\n\n    \u0026lt;groupId\u0026gt;dubbo-sb-demo\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;com.xlauch.dubbo\u0026lt;/artifactId\u0026gt;\n    \u0026lt;packaging\u0026gt;pom\u0026lt;/packaging\u0026gt;\n    \u0026lt;version\u0026gt;1.0-SNAPSHOT\u0026lt;/version\u0026gt;\n\n\n    \u0026lt;modules\u0026gt;\n        \u0026lt;module\u0026gt;dubbo-sb-demo-api\u0026lt;/module\u0026gt;\n        \u0026lt;module\u0026gt;dubbo-sb-demo-consumer\u0026lt;/module\u0026gt;\n        \u0026lt;module\u0026gt;dubbo-sb-demo-provider\u0026lt;/module\u0026gt;\n    \u0026lt;/modules\u0026gt;\n\n    \u0026lt;properties\u0026gt;\n        \u0026lt;java.version\u0026gt;1.8\u0026lt;/java.version\u0026gt;\n        \u0026lt;project.build.sourceEncoding\u0026gt;UTF-8\u0026lt;/project.build.sourceEncoding\u0026gt;\n        \u0026lt;project.reporting.outputEncoding\u0026gt;UTF-8\u0026lt;/project.reporting.outputEncoding\u0026gt;\n\n        \u0026lt;springboot-version\u0026gt;2.0.2.RELEASE\u0026lt;/springboot-version\u0026gt;\n        \u0026lt;dubbo-springboot-version\u0026gt;0.2.0\u0026lt;/dubbo-springboot-version\u0026gt;\n        \u0026lt;zkclient.version\u0026gt;0.9\u0026lt;/zkclient.version\u0026gt;\n    \u0026lt;/properties\u0026gt;\n\n\u0026lt;/project\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-api工程\" class=\"anchor\" href=\"#2-api%E5%B7%A5%E7%A8%8B\"\u003E\u003C/a\u003E2. api工程\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E声明接口\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/3/7\n */\npublic interface HelloService {\n\n    /**\n     * hello\n     * @param name\n     * @return\n     */\n    public String sayHello(String name) ;\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-实现-dubbo-服务提供方\" class=\"anchor\" href=\"#2-%E5%AE%9E%E7%8E%B0-dubbo-%E6%9C%8D%E5%8A%A1%E6%8F%90%E4%BE%9B%E6%96%B9\"\u003E\u003C/a\u003E2. 实现 Dubbo 服务提供方\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) pom.xml 依赖\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n\u0026lt;project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u0026gt;\n    \u0026lt;parent\u0026gt;\n        \u0026lt;artifactId\u0026gt;com.xlauch.dubbo\u0026lt;/artifactId\u0026gt;\n        \u0026lt;groupId\u0026gt;dubbo-sb-demo\u0026lt;/groupId\u0026gt;\n        \u0026lt;version\u0026gt;1.0-SNAPSHOT\u0026lt;/version\u0026gt;\n    \u0026lt;/parent\u0026gt;\n    \u0026lt;modelVersion\u0026gt;4.0.0\u0026lt;/modelVersion\u0026gt;\n\n    \u0026lt;artifactId\u0026gt;dubbo-sb-demo-provider\u0026lt;/artifactId\u0026gt;\n\n    \u0026lt;dependencies\u0026gt;\n        \u0026lt;!-- 本地api dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;${project.groupId}\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-sb-demo-api\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${project.version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- Spring Boot dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-web\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-actuator\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- dubbo dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-starter\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-actuator\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- zookeeper dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.101tec\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;zkclient\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${zkclient.version}\u0026lt;/version\u0026gt;\n            \u0026lt;exclusions\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-api\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;log4j\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;log4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-log4j12\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n            \u0026lt;/exclusions\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n\n    \u0026lt;/dependencies\u0026gt;\n\n    \u0026lt;dependencyManagement\u0026gt;\n        \u0026lt;dependencies\u0026gt;\n            \u0026lt;dependency\u0026gt;\n                \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n                \u0026lt;artifactId\u0026gt;spring-boot-starter-parent\u0026lt;/artifactId\u0026gt;\n                \u0026lt;version\u0026gt;${springboot-version}\u0026lt;/version\u0026gt;\n                \u0026lt;type\u0026gt;pom\u0026lt;/type\u0026gt;\n                \u0026lt;scope\u0026gt;import\u0026lt;/scope\u0026gt;\n            \u0026lt;/dependency\u0026gt;\n        \u0026lt;/dependencies\u0026gt;\n    \u0026lt;/dependencyManagement\u0026gt;\n\n    \u0026lt;repositories\u0026gt;\n        \u0026lt;repository\u0026gt;\n            \u0026lt;id\u0026gt;sonatype-nexus-snapshots\u0026lt;/id\u0026gt;\n            \u0026lt;url\u0026gt;https://oss.sonatype.org/content/repositories/snapshots\u0026lt;/url\u0026gt;\n            \u0026lt;releases\u0026gt;\n                \u0026lt;enabled\u0026gt;false\u0026lt;/enabled\u0026gt;\n            \u0026lt;/releases\u0026gt;\n            \u0026lt;snapshots\u0026gt;\n                \u0026lt;enabled\u0026gt;true\u0026lt;/enabled\u0026gt;\n            \u0026lt;/snapshots\u0026gt;\n        \u0026lt;/repository\u0026gt;\n    \u0026lt;/repositories\u0026gt;\n\u0026lt;/project\u0026gt;\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E注意：zookeeper移除log4j相关包\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(2) 实现接口\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.dubbo.demo.consumer.service;\n\n\nimport com.alibaba.dubbo.config.annotation.Service;\nimport com.xlauch.dubbo.demo.api.service.HelloService;\nimport com.xlauch.dubbo.demo.api.pojo.User;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@Service(\n        version = \"${demo.service.version}\",\n        application = \"${dubbo.application.id}\",\n        protocol = \"${dubbo.protocol.id}\",\n        registry = \"${dubbo.registry.id}\"\n)\npublic class HelloServiceImpl implements HelloService {\n\n    @Override\n    public String sayHello(String name) {\n        return \"hello水电费 : \" + name;\n    }\n\n    @Override\n    public String addUser(User user) {\n        return user.toString();\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(3) 编写 Spring Boot 启动类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\nimport org.springframework.boot.builder.SpringApplicationBuilder;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@SpringBootApplication\npublic class DubboProviderDemo {\n\n    public static void main(String[] args) {\n\n        new SpringApplicationBuilder(DubboProviderDemo.class)\n                .web(false) // 非 Web 应用\n                .run(args);\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(4) 配置 application.properties\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# Spring boot application\nspring.application.name=dubbo-provider-demo\nserver.port=9090\nmanagement.server.port=9091\n\n# Service version\ndemo.service.version=1.0.0\n# Base packages to scan Dubbo Components (e.g @Service , @Reference)\ndubbo.scan.basePackages=com.xlauch.dubbo.demo.consumer.service\n\n# Dubbo Config properties\n## ApplicationConfig Bean\ndubbo.application.id=dubbo-provider-demo\ndubbo.application.name=dubbo-provider-demo\n\n## ProtocolConfig Bean\ndubbo.protocol.id=dubbo\ndubbo.protocol.name=dubbo\ndubbo.protocol.port=12345\n\n## RegistryConfig Bean\ndubbo.registry.id=my-registry\ndubbo.registry.address=zookeeper://127.0.0.1:2181\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-实现-dubbo-服务消费方\" class=\"anchor\" href=\"#3-%E5%AE%9E%E7%8E%B0-dubbo-%E6%9C%8D%E5%8A%A1%E6%B6%88%E8%B4%B9%E6%96%B9\"\u003E\u003C/a\u003E3. 实现 Dubbo 服务消费方\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) pom.xml 依赖\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;?xml version=\"1.0\" encoding=\"UTF-8\"?\u0026gt;\n\u0026lt;project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n         xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\"\u0026gt;\n    \u0026lt;parent\u0026gt;\n        \u0026lt;artifactId\u0026gt;com.xlauch.dubbo\u0026lt;/artifactId\u0026gt;\n        \u0026lt;groupId\u0026gt;dubbo-sb-demo\u0026lt;/groupId\u0026gt;\n        \u0026lt;version\u0026gt;1.0-SNAPSHOT\u0026lt;/version\u0026gt;\n    \u0026lt;/parent\u0026gt;\n    \u0026lt;modelVersion\u0026gt;4.0.0\u0026lt;/modelVersion\u0026gt;\n\n    \u0026lt;artifactId\u0026gt;dubbo-sb-demo-consumer\u0026lt;/artifactId\u0026gt;\n    \u0026lt;dependencies\u0026gt;\n        \u0026lt;!-- 本地api dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;${project.groupId}\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-sb-demo-api\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${project.version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- Spring Boot dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-web\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;spring-boot-starter-actuator\u0026lt;/artifactId\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- dubbo dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-starter\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.alibaba.boot\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;dubbo-spring-boot-actuator\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${dubbo-springboot-version}\u0026lt;/version\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n        \u0026lt;!-- zookeeper dependencies --\u0026gt;\n        \u0026lt;dependency\u0026gt;\n            \u0026lt;groupId\u0026gt;com.101tec\u0026lt;/groupId\u0026gt;\n            \u0026lt;artifactId\u0026gt;zkclient\u0026lt;/artifactId\u0026gt;\n            \u0026lt;version\u0026gt;${zkclient.version}\u0026lt;/version\u0026gt;\n            \u0026lt;exclusions\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-api\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;log4j\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;log4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n                \u0026lt;exclusion\u0026gt;\n                    \u0026lt;artifactId\u0026gt;slf4j-log4j12\u0026lt;/artifactId\u0026gt;\n                    \u0026lt;groupId\u0026gt;org.slf4j\u0026lt;/groupId\u0026gt;\n                \u0026lt;/exclusion\u0026gt;\n            \u0026lt;/exclusions\u0026gt;\n        \u0026lt;/dependency\u0026gt;\n\n\n    \u0026lt;/dependencies\u0026gt;\n\n    \u0026lt;dependencyManagement\u0026gt;\n        \u0026lt;dependencies\u0026gt;\n            \u0026lt;dependency\u0026gt;\n                \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n                \u0026lt;artifactId\u0026gt;spring-boot-starter-parent\u0026lt;/artifactId\u0026gt;\n                \u0026lt;version\u0026gt;${springboot-version}\u0026lt;/version\u0026gt;\n                \u0026lt;type\u0026gt;pom\u0026lt;/type\u0026gt;\n                \u0026lt;scope\u0026gt;import\u0026lt;/scope\u0026gt;\n            \u0026lt;/dependency\u0026gt;\n        \u0026lt;/dependencies\u0026gt;\n    \u0026lt;/dependencyManagement\u0026gt;\n\n\u0026lt;/project\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) 通过 @Reference 注入 HelloService\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.dubbo.demo.consumer.controller;\n\n\nimport com.alibaba.dubbo.config.annotation.Reference;\nimport com.xlauch.dubbo.demo.api.service.HelloService;\nimport org.springframework.web.bind.annotation.RequestMapping;\nimport org.springframework.web.bind.annotation.RequestParam;\nimport org.springframework.web.bind.annotation.RestController;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@RestController\npublic class HelloController {\n\n    @Reference(version = \"${demo.service.version}\",\n            application = \"${dubbo.application.id}\",\n            timeout = 3000)\n    private HelloService helloService;\n\n    @RequestMapping(\"/sayHello\")\n    public String sayHello(@RequestParam String name) {\n        return helloService.sayHello(name);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(2) 编写 Spring Boot 启动类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.dubbo.demo.consumer;\n\n\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/8/16\n */\n@SpringBootApplication\npublic class DubboConsumerDemo {\n\n    public static void main(String[] args) {\n\n        SpringApplication.run(DubboConsumerDemo.class, args);\n\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(3) 配置 application.properties\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# Spring boot application\nspring.application.name = dubbo-consumer-demo\nserver.port = 8080\nmanagement.server.port = 8081\n\n# Service Version\ndemo.service.version = 1.0.0\n\n# Dubbo Config properties\n## ApplicationConfig Bean\ndubbo.application.id = dubbo-consumer-demo\ndubbo.application.name = dubbo-consumer-demo\n\n## ProtocolConfig Bean\ndubbo.protocol.id = dubbo\ndubbo.protocol.name = dubbo\ndubbo.protocol.port = 12345\n\ndubbo.registry.id=my-registry\ndubbo.registry.address=zookeeper://127.0.0.1:2181\n\u003C/code\u003E\u003C/pre\u003E","988113":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"http://doc.redisfans.com/\"\u003ERedis 命令参考\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.runoob.com/redis/redis-tutorial.html\"\u003ERedis 教程\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/152223_3f674bf9_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","1047311":"\u003Ch3\u003E\n\u003Ca id=\"1-redis-requires-ruby-version--222问题\" class=\"anchor\" href=\"#1-redis-requires-ruby-version--222%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E1. redis requires Ruby version \u0026gt;= 2.2.2问题\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 1.安装curl\n\nsudo yum install curl\n\n\n# 2. 设置公钥\n\ngpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB\n\n# 3. 安装RVM\n\ncurl -L get.rvm.io | bash -s stable \n \nsource /usr/local/rvm/scripts/rvm\n\n# 4. 查看rvm库中已知的ruby版本\n\nrvm list known\n\n# 5. 安装一个ruby版本\n\nrvm install 2.4.4\n\n# 6. 使用一个ruby版本\n\nrvm use 2.4.4\n\n# 7. 设置默认版本\n\nrvm remove 2.0.0\n\n# 8. 卸载一个已知版本\n\nruby --version\n\n# 9. 再安装redis就可以了\n\ngem install redis\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-redis-集群-创建报错-err-node-is-not-empty-either-the-node-already-knows-other-nodes\" class=\"anchor\" href=\"#2-redis-%E9%9B%86%E7%BE%A4-%E5%88%9B%E5%BB%BA%E6%8A%A5%E9%94%99-err-node-is-not-empty-either-the-node-already-knows-other-nodes\"\u003E\u003C/a\u003E2. redis 集群 创建报错 [ERR] Node is not empty. Either the node already knows other nodes\u003C/h3\u003E\n\u003Col class=\"task-list\"\u003E\n\u003Cli\u003E将每个节点下aof、rdb、nodes.conf本地备份文件删除；\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E mv nodes-700*.conf ./bak/\n mv appendonly.aof ./bak/\n mv dump.rdb ./bak/\n\u003C/code\u003E\u003C/pre\u003E\n\u003Col start=\"2\" class=\"task-list\"\u003E\n\u003Cli\u003E172.168.63.201:7001\u0026gt; flushdb #清空当前数据库(可省略)\u003C/li\u003E\n\u003Cli\u003E之后再执行脚本，成功执行；\u003C/li\u003E\n\u003C/ol\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-redis-cluster-warning-node-1270017003-has-slots-in-migrating-state-15495\" class=\"anchor\" href=\"#3-redis-cluster-warning-node-1270017003-has-slots-in-migrating-state-15495\"\u003E\u003C/a\u003E3. Redis Cluster [WARNING] Node 127.0.0.1:7003 has slots in migrating state (15495).\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E解决办法2：登入提示错误的两个节点执行以下清除命令\n\ncluster setslot 15495 stable\n\u003C/code\u003E\u003C/pre\u003E","679019":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo静态static-synchronized-变成class-锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E9%9D%99%E6%80%81static-synchronized-%E5%8F%98%E6%88%90class-%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo（静态static synchronized 变成class 锁）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.base.sync002;\n\n/**\n * 关键字synchronized取得的锁都是对象锁，而不是把一段代码（方法）当做锁，\n * 所以代码中哪个线程先执行synchronized关键字的方法，哪个线程就持有该方法所属对象的锁（Lock），\n * \u0026lt;p\u0026gt;\n * 在静态方法上加synchronized关键字，表示锁定.class类，类一级别的锁（独占.class类）。\n *\n * @author alienware\n */\npublic class MultiThread {\n\n    private int num = 0;\n\n    /**\n     * static\n     */\n    public synchronized void printNum(String tag) {\n        try {\n\n            if (tag.equals(\"a\")) {\n                num = 100;\n                System.out.println(\"tag a, set num over!\");\n                Thread.sleep(1000);\n            } else {\n                num = 200;\n                System.out.println(\"tag b, set num over!\");\n            }\n\n            System.out.println(\"tag \" + tag + \", num = \" + num);\n\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n\n    /**\n     * 注意观察run方法输出顺序\n     *\n     * @param args\n     */\n    public static void main(String[] args) {\n\n        //俩个不同的对象\n        final MultiThread m1 = new MultiThread();\n        final MultiThread m2 = new MultiThread();\n\n        Thread t1 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                m1.printNum(\"a\");\n            }\n        });\n\n        Thread t2 = new Thread(new Runnable() {\n            @Override\n            public void run() {\n                m2.printNum(\"b\");\n            }\n        });\n\n        t1.start();\n        t2.start();\n\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"printNum\"方法不加static时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/095201_b13ac50e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"printNum\"方法加上static时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/095233_f14f5e61_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-案例说明\" class=\"anchor\" href=\"#2-%E6%A1%88%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 案例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关键字synchronized取得的锁都是对象锁\u003C/li\u003E\n\u003Cli\u003E在静态方法上加synchronized关键字，表示锁定.class类，类一级别的锁（独占.class类）。\u003C/li\u003E\n\u003C/ul\u003E","688448":"\u003Ch3\u003E\n\u003Ca id=\"多线程下单例解决方案\" class=\"anchor\" href=\"#%E5%A4%9A%E7%BA%BF%E7%A8%8B%E4%B8%8B%E5%8D%95%E4%BE%8B%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88\"\u003E\u003C/a\u003E多线程下单例解决方案\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E方案1：多次确认\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class DubbleSingleton {\n\n\tprivate static DubbleSingleton ds;\n\t\n\tpublic  static DubbleSingleton getDs(){\n\t\tif(ds == null){\n\t\t\ttry {\n\t\t\t\t//模拟初始化对象的准备时间...\n\t\t\t\tThread.sleep(3000);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\tsynchronized (DubbleSingleton.class) {\n\t\t\t\tif(ds == null){\n\t\t\t\t\tds = new DubbleSingleton();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn ds;\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSystem.out.println(DubbleSingleton.getDs().hashCode());\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSystem.out.println(DubbleSingleton.getDs().hashCode());\n\t\t\t}\n\t\t},\"t2\");\n\t\tThread t3 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSystem.out.println(DubbleSingleton.getDs().hashCode());\n\t\t\t}\n\t\t},\"t3\");\n\t\t\n\t\tt1.start();\n\t\tt2.start();\n\t\tt3.start();\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E同步块中，一定要再次验证：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esynchronized (DubbleSingleton.class) {\n     if(ds == null){\n\tds = new DubbleSingleton();\n     }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E方案2：内部类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Singletion {\n\t\n\tprivate static class InnerSingletion {\n\t\tprivate static Singletion single = new Singletion();\n\t}\n\t\n\tpublic static Singletion getInstance(){\n\t\treturn InnerSingletion.single;\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E","688445":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Queue {\n\n    /**\n     * 1 创建一个集合，存储对象\n     */\n    private static LinkedList\u0026lt;Object\u0026gt; list = new LinkedList\u0026lt;Object\u0026gt;();\n\n\n    /**\n     * 2 计数\n     */\n    private AtomicInteger count = new AtomicInteger(0);\n\n    /**\n     * 3 定义存储上限、下限\n     */\n    private int maxSize = 5;\n\n    private int minSize = 0;\n\n    /**\n     * 4 创建构造\n     *\n     * @param maxSize\n     */\n    public Queue(int maxSize) {\n        this.maxSize = maxSize;\n    }\n\n    /**\n     * 5 定义锁对象\n     */\n    private Object lock = new Object();\n\n\n    /**\n     * 存入对象\n     *\n     * @param object\n     */\n    public void put(Object object) {\n        synchronized (lock) {\n            if (count.get() == this.maxSize) {\n                try {\n                    lock.wait();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }\n\n\n            list.add(object);\n            count.incrementAndGet();\n            lock.notify();\n            System.out.println(\"存入对象: \" + object);\n        }\n    }\n\n\n    /**\n     * 获取对象\n     *\n     * @return\n     */\n    public Object get() {\n        Object ret = null ;\n        synchronized (lock){\n            if (count.get() == this.minSize){\n                try {\n                    lock.wait();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }\n\n            ret = list.removeFirst();\n            count.decrementAndGet();\n            lock.notify();\n            System.out.println(\"获取对象：\" + ret);\n        }\n        return ret ;\n    }\n\n\n    public static void  main(String[] args) {\n        final Queue queue = new Queue(5);\n\n        queue.put(\"a\");\n        queue.put(\"b\");\n        queue.put(\"c\");\n        queue.put(\"d\");\n        queue.put(\"e\");\n\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                queue.put(\"f\");\n                queue.put(\"g\");\n            }\n        }).start();\n\n        new Thread(new Runnable() {\n            @Override\n            public void run() {\n                queue.get();\n                try {\n                    Thread.sleep(1000);\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n                queue.get();\n            }\n        }).start();\n    }\n\n\n}\n\u003C/code\u003E\u003C/pre\u003E","731113":"\u003Ch3\u003E\n\u003Ca id=\"1-executor\" class=\"anchor\" href=\"#1-executor\"\u003E\u003C/a\u003E1. Executor\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EJava线程池的超级接口；提供一个execute(Runnable command)方法;我们一般用它的继承接口ExecutorService。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-executorservice它是线程池定义的一个接口继承executor有两个实现类分别为threadpoolexecutorscheduledthreadpoolexecutor\" class=\"anchor\" href=\"#2-executorservice%E5%AE%83%E6%98%AF%E7%BA%BF%E7%A8%8B%E6%B1%A0%E5%AE%9A%E4%B9%89%E7%9A%84%E4%B8%80%E4%B8%AA%E6%8E%A5%E5%8F%A3%E7%BB%A7%E6%89%BFexecutor%E6%9C%89%E4%B8%A4%E4%B8%AA%E5%AE%9E%E7%8E%B0%E7%B1%BB%E5%88%86%E5%88%AB%E4%B8%BAthreadpoolexecutorscheduledthreadpoolexecutor\"\u003E\u003C/a\u003E2. ExecutorService：它是线程池定义的一个接口，继承Executor。有两个实现类，分别为ThreadPoolExecutor,ScheduledThreadPoolExecutor。\u003C/h4\u003E\n\u003Cp\u003E线程池的继承树：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0906/151553_f286d769_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-executorservice常用的几个方法\" class=\"anchor\" href=\"#3-executorservice%E5%B8%B8%E7%94%A8%E7%9A%84%E5%87%A0%E4%B8%AA%E6%96%B9%E6%B3%95\"\u003E\u003C/a\u003E3. ExecutorService常用的几个方法：\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eexecute(Runnable)：方法接收一个Runnable实例，并且异步的执行\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo1 {\n    \n    public static void main(String[] args) {\n        ExecutorService executorService = Executors.newSingleThreadExecutor(); //创建一个单线程\n        executorService.execute(new Runnable() { //接收一个Runnable实例\n            public void run() {\n                System.out.println(\"Asynchronous task\");\n            }\n        });\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esubmit(Runnable)：返回一个Future对象，通过返回的Future对象，我们可以检查提交的任务是否执行完毕\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo2 {\n    \n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor(); //创建一个单线程\n        Future future = executorService.submit(new Runnable() { //接收一个Runnable实例\n            public void run() {\n                System.out.println(\"Asynchronous task\");\n            }\n        });\n        System.out.println(future.get()); //任务执行结束返回null.\n        executorService.shutdown();\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esubmit(Callable)：与submit(Callable)类似，也会返回一个Future对象，但是除此之外，submit(Callable)接收的是一个Callable的实现，Callable接口中的call()方法有一个返回值，可以返回任务的执行结果，而Runnable接口中的run()方法是void的，没有返回值\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo1 {\n    \n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor(); //创建一个单线程\n        Future\u0026lt;Object\u0026gt; future = executorService.submit(new Callable\u0026lt;Object\u0026gt;() { //接收一个Callable实例\n            public Object call() {\n                System.out.println(\"Asynchronous task\");\n                return \"Callable Result\";\n            }\n        });\n        System.out.println(\"future.get()=\"+future.get());\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EinvokeAny(...)：方法接收的是一个Callable的集合，执行这个方法不会返回Future，但是会返回所有Callable任务中其中一个任务的执行结果。这个方法也无法保证返回的是哪个任务的执行结果，反正是其中的某一个。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo2 {\n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Set\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt; callables = new HashSet\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt;();\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result1\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result2\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result3\";\n            }\n            \n        });\n        \n        String result = executorService.invokeAny(callables);        \n        System.out.println(result);\n        executorService.shutdown();\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EinvokeAll(...)：与 invokeAny(...)类似也是接收一个Callable集合，但是前者执行之后会返回一个Future的List，其中对应着每个Callable任务执行后的Future对象。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Demo3 {\n\n    public static void main(String[] args) throws InterruptedException, ExecutionException {\n        ExecutorService executorService = Executors.newSingleThreadExecutor();\n        Set\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt; callables = new HashSet\u0026lt;Callable\u0026lt;String\u0026gt;\u0026gt;();\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result1\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result2\";\n            }\n            \n        });\n        \n        callables.add(new Callable\u0026lt;String\u0026gt;(){\n            @Override\n            public String call() throws Exception {\n                // TODO Auto-generated method stub\n                return \"Result3\";\n            }\n            \n        });\n        \n        List\u0026lt;Future\u0026lt;String\u0026gt;\u0026gt; futures = executorService.invokeAll(callables);    //返回一个Future的List集合    \n        for(Future\u0026lt;String\u0026gt; future:futures){\n            System.out.println(\"future.get()=\"+future.get());\n        }\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eshutdown()：我们使用完成ExecutorService之后应该关闭它，否则它里面的线程会一直处于运行状态。\u003C/li\u003E\n\u003C/ul\u003E","736292":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Random;\nimport java.util.concurrent.BrokenBarrierException;\nimport java.util.concurrent.CyclicBarrier;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/10\n */\npublic class TestCyclicBarrier {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    /**\n     * 国家测试类\n     */\n    static class Country implements Runnable {\n        private CyclicBarrier barrier;\n\n        private String name;\n\n        Country(CyclicBarrier barrier, String name) {\n            this.barrier = barrier;\n            this.name = name;\n        }\n\n        @Override\n        public void run() {\n            System.out.println(FORMAT.format(new Date()) +  name + \" 开始准备...\");\n            try {\n                Thread.sleep(new Random().nextInt(3000));\n                barrier.await();\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            } catch (BrokenBarrierException e) {\n                e.printStackTrace();\n            }\n\n            System.out.println(FORMAT.format(new Date()) + \"=======================\" + name + \" 准备结束...\");\n        }\n    }\n\n    public static void main(String[] args) {\n        final CyclicBarrier barrier = new CyclicBarrier(5);\n\n        ExecutorService executorService = Executors.newFixedThreadPool(5);\n        executorService.execute(new Country(barrier, \"中国\"));\n        executorService.execute(new Country(barrier, \"美国\"));\n        executorService.execute(new Country(barrier, \"英国\"));\n        executorService.execute(new Country(barrier, \"法国\"));\n        executorService.execute(new Country(barrier, \"小日本\"));\n\n        executorService.shutdown();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003ECyclicBarrier 的字面意思是可循环使用（Cyclic）的屏障（Barrier）。它要做的事情是，让一组线程到达一个屏障（也可以叫同步点）时被阻塞，直到最后一个线程到达屏障时，屏障才会开门，所有被屏障拦截的线程才会继续干活。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003ECyclicBarrier默认的构造方法是CyclicBarrier(int parties)，其参数表示屏障拦截的线程数量，每个线程调用await方法告诉CyclicBarrier我已经到达了屏障，然后当前线程被阻塞。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003ECyclicBarrier强调的是n个线程，大家相互等待，只要有一个没完成，所有人都得等着。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-cyclicbarrier和countdownlatch的区别\" class=\"anchor\" href=\"#3-cyclicbarrier%E5%92%8Ccountdownlatch%E7%9A%84%E5%8C%BA%E5%88%AB\"\u003E\u003C/a\u003E3. CyclicBarrier和CountDownLatch的区别\u003C/h3\u003E\n\u003Cp\u003E（1）CountDownLatch的计数器只能使用一次。而CyclicBarrier的计数器可以使用reset() 方法重置。所以CyclicBarrier能处理更为复杂的业务场景，比如如果计算发生错误，可以重置计数器，并让线程们重新执行一次。\u003C/p\u003E\n\u003Cp\u003E（2）CyclicBarrier还提供其他有用的方法，比如getNumberWaiting方法可以获得CyclicBarrier阻塞的线程数量。isBroken方法用来知道阻塞的线程是否被中断。比如以下代码执行完之后会返回true。\u003C/p\u003E\n\u003Cp\u003E（3）CountDownLatch会阻塞主线程，CyclicBarrier不会阻塞主线程，只会阻塞子线程。\u003C/p\u003E","799824":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.height.lock020.fxz;\n\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.locks.Condition;\nimport java.util.concurrent.locks.Lock;\nimport java.util.concurrent.locks.ReentrantLock;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/25\n */\npublic class TestLockCondition {\n\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n\n    /**\n     * 定义锁\n     */\n    private Lock lock = new ReentrantLock();\n\n    /**\n     * 定义锁条件\n     */\n    private Condition condition1 = lock.newCondition();\n\n    private Condition condition2 = lock.newCondition();\n\n\n    /**\n     * 等待方法\n     */\n    public void doWait() {\n        try {\n            lock.lock();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"进入等待\");\n            condition1.await();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"继续\");\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n    /**\n     * 等待方法\n     */\n    public void doWait2() {\n        try {\n            lock.lock();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"进入等待\");\n            condition2.await();\n            System.out.println(FORMAT.format(new Date()) + \"  线程 \" + Thread.currentThread().getName() + \"继续\");\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n\n\n    /**\n     * 唤醒方法\n     */\n    public void doNotify() {\n        try {\n            lock.lock();\n            Thread.sleep(1000);\n            condition1.signalAll();\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n    public void doNotify2() {\n        try {\n            lock.lock();\n            Thread.sleep(1000);\n            condition2.signal();\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        } finally {\n            lock.unlock();\n        }\n    }\n\n\n    public static void main(String[] args) throws InterruptedException {\n\n        final TestLockCondition test = new TestLockCondition();\n        /**\n         * 多线程执行，需要等上一线程执行完成，下一个线程才能开始\n         */\n        for (int i = 0; i \u0026lt; 3; i++) {\n            new Thread(() -\u0026gt; {\n                test.doWait();\n            }, \"t\" + i).start();\n        }\n\n\n        Thread.sleep(1000);\n        System.out.println(\"============================\");\n        new Thread(() -\u0026gt; {\n            test.doWait2();\n        }, \"t3\" ).start();\n\n        Thread.sleep(2000);\n        System.out.println(\"============================唤醒前三个线程\");\n        test.doNotify();\n\n        new Thread(() -\u0026gt; {\n            test.doNotify2();\n        }, \"t4\" ).start();\n    }\n\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0926/110346_d9fe103d_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Econdition必须结合Lock对象一起使用\u003C/li\u003E\n\u003Cli\u003E多个condition互不影响\u003C/li\u003E\n\u003C/ul\u003E","820044":"\u003Ch3\u003E\n\u003Ca id=\"1定义evenet类\" class=\"anchor\" href=\"#1%E5%AE%9A%E4%B9%89evenet%E7%B1%BB\"\u003E\u003C/a\u003E1、定义Evenet类\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEvent {\n\n    private int id;\n\n    private String name;\n\n    public UserEvent(){\n    }\n\n    public UserEvent(int id , String name) {\n        this.id = id ;\n        this.name = name;\n    }\n\n    @Override\n    public String toString() {\n        return \"UserEvent{\" +\n                \"id=\" + id +\n                \", name='\" + name + '\\'' +\n                '}';\n    }\n\n    public int getId() {\n        return id;\n    }\n\n    public void setId(int id) {\n        this.id = id;\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2定义eventfactory\" class=\"anchor\" href=\"#2%E5%AE%9A%E4%B9%89eventfactory\"\u003E\u003C/a\u003E2、定义EventFactory\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.EventFactory;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventFactory implements EventFactory {\n\n    @Override\n    public Object newInstance() {\n        return new UserEvent();\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E3、定义事件句柄（事件消费者）\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.EventHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventHandler implements EventHandler\u0026lt;UserEvent\u0026gt; {\n\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(UserEvent userEvent, long l, boolean b) throws Exception {\n        System.out.println(FORMAT.format(new Date()) +  userEvent);\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4定义eventproducer\" class=\"anchor\" href=\"#4%E5%AE%9A%E4%B9%89eventproducer\"\u003E\u003C/a\u003E4、定义EventProducer\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventProducer {\n\n    private RingBuffer\u0026lt;UserEvent\u0026gt; ringBuffer ;\n\n    public UserEventProducer(RingBuffer\u0026lt;UserEvent\u0026gt; ringBuffer) {\n        this.ringBuffer = ringBuffer ;\n    }\n\n\n    public void onData(UserEvent userEvent) {\n        // 1. 获取下一个可用序号\n        long sequence = ringBuffer.next() ;\n\n        try {\n            // 2. 获取缓存中的对象\n            UserEvent temp = ringBuffer.get(sequence);\n            // 3. 赋值对象\n            temp.setId(userEvent.getId());\n            temp.setName(userEvent.getName());\n        }catch (Exception e){\n            e.printStackTrace();\n        } finally {\n            // 4. 发布\n            ringBuffer.publish(sequence);\n        }\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1、 获取下一个可用序号\u003C/li\u003E\n\u003Cli\u003E2、 获取缓存中的对象\u003C/li\u003E\n\u003Cli\u003E3、 赋值对象\u003C/li\u003E\n\u003Cli\u003E4、 发布\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5测试\" class=\"anchor\" href=\"#5%E6%B5%8B%E8%AF%95\"\u003E\u003C/a\u003E5、测试\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.RingBuffer;\nimport com.lmax.disruptor.YieldingWaitStrategy;\nimport com.lmax.disruptor.dsl.Disruptor;\nimport com.lmax.disruptor.dsl.ProducerType;\n\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/27\n */\npublic class UserEventMain {\n\n    public static void main(String[] args) {\n        long start = System.currentTimeMillis() ;\n\n        // 创建线程池\n        ExecutorService executor = Executors.newCachedThreadPool();\n\n        // 创建事件工厂\n        UserEventFactory eventFactory = new UserEventFactory();\n\n        // 指定ringbuffer大小 ，必须是2的N次方\n        int ringBufferSize = 1024 * 1024;\n\n        /**\n         * 创建disruptor\n         * @param eventFactory      ： 创建事件工厂\n         * @param ringBufferSize    ： ringbuffer大小 ，必须是2的N次方\n         * @param executor          : 线程池\n         * @param producerType      : 生产者类型\n         *                                  ProducerType.SINGLE：单个生产者\n         *                                  ProducerType.MULTI: 多个生产者\n         * @param waitStrategy      : 等待策略\n         *                                  BlockingWaitStrategy 是最低效的策略，但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现\n         *                                  SleepingWaitStrategy 的性能表现跟BlockingWaitStrategy差不多，对CPU的消耗也类似，但其对生产者线程的影响最小，适合用于异步日志类似的场景\n         *                                  YieldingWaitStrategy 的性能是最好的，适合用于低延迟的系统。在要求极高性能且事件处理线数小于CPU逻辑核心数的场景中，推荐使用此策略；例如，CPU开启超线程的特性\n         */\n        Disruptor\u0026lt;UserEvent\u0026gt; disruptor = new Disruptor\u0026lt;UserEvent\u0026gt;(eventFactory, ringBufferSize, executor, ProducerType.SINGLE, new YieldingWaitStrategy());\n\n        // 连接消费事件方法\n        disruptor.handleEventsWith(new UserEventHandler());\n\n        // 启动\n        disruptor.start();\n\n        // 发布事件\n        publish(disruptor.getRingBuffer());\n\n        // 关闭 disruptor，方法会堵塞，直至所有的事件都得到处理；\n        disruptor.shutdown();\n\n        // 关闭 disruptor 使用的线程池；如果需要的话，必须手动关闭， disruptor 在 shutdown 时不会自动关闭；\n        executor.shutdown();\n\n        System.out.println(\"耗时：\" + (System.currentTimeMillis() - start) + \"ms\");\n    }\n\n    /**\n     * 发布事件\n     * @param ringBuffer\n     */\n    private static void publish(RingBuffer\u0026lt;UserEvent\u0026gt; ringBuffer) {\n        UserEventProducer producer = new UserEventProducer(ringBuffer);\n        int count = 600 * 10000 ;\n        for (int i = 1 ; i \u0026lt;= count ; i++) {\n            producer.onData(new UserEvent(i , \"name_\" + i));\n        }\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E","1094082":"\u003Cp\u003EDocker 容器镜像删除\u003C/p\u003E\n\u003Cp\u003E1.停止所有的容器\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Edocker stop $(docker ps -q)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E2.强制移除此容器\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Edocker rm -f mysql1\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E3.清理此容器的网络占用\u003C/p\u003E\n\u003Cp\u003E格式：docker network disconnect --force 网络模式 容器名称\u003C/p\u003E\n\u003Cp\u003E示例：docker network disconnect --force bridge mysql1\u003C/p\u003E\n\u003Cp\u003E4.简查是否还有同名容器占用\u003C/p\u003E\n\u003Cp\u003E格式：docker network inspect 网络模式\n示例：docker network inspect bridge\u003C/p\u003E\n\u003Cp\u003E5.重新构建容器\u003C/p\u003E\n\u003Cp\u003Edocker run --name mysql1 -d -p3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:latest\u003C/p\u003E\n\u003Cp\u003E1.停止所有的container，这样才能够删除其中的images：\u003C/p\u003E\n\u003Cp\u003Edocker stop $(docker ps -a -q)\u003C/p\u003E\n\u003Cp\u003E如果想要删除所有container的话再加一个指令：\u003C/p\u003E\n\u003Cp\u003Edocker rm $(docker ps -a -q)\u003C/p\u003E\n\u003Cp\u003E2.查看当前有些什么images\u003C/p\u003E\n\u003Cp\u003Edocker images\u003C/p\u003E\n\u003Cp\u003E3.删除images，通过image的id来指定删除谁\u003C/p\u003E\n\u003Cp\u003Edocker rmi \u003C/p\u003E\n\u003Cp\u003E想要删除untagged images，也就是那些id为的image的话可以用\u003C/p\u003E\n\u003Cp\u003Edocker rmi $(docker images | grep \"^\" | awk \"{print $3}\")\u003C/p\u003E\n\u003Cp\u003E要删除全部image的话\u003C/p\u003E\n\u003Cp\u003Edocker rmi $(docker images -q)\u003C/p\u003E","987023":"\u003Ch3\u003E\n\u003Ca id=\"1-安装准备\" class=\"anchor\" href=\"#1-%E5%AE%89%E8%A3%85%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E1. 安装准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E首先从官网上下载\u003Ca href=\"https://tomcat.apache.org/download-80.cgi\"\u003E tomcat8 \u003C/a\u003E\n\u003C/li\u003E\n\u003Cli\u003E解压：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf apache-tomcat-8.5.30.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动tomcat\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd bin\n./startup.sh\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-配置多个tomcat\" class=\"anchor\" href=\"#2-%E9%85%8D%E7%BD%AE%E5%A4%9A%E4%B8%AAtomcat\"\u003E\u003C/a\u003E2. 配置多个tomcat\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E远程停服务端口，默认8005，如下改为8006\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Server port=\"8006\" shutdown=\"SHUTDOWN\"\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EHTTP端口，默认8080，如下改为8081\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E其中8081为HTTP端口，8443为HTTPS端口\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Connector port=\"8081\" protocol=\"HTTP/1.1\"   \n               connectionTimeout=\"60000\"   \n               redirectPort=\"8443\" disableUploadTimeout=\"false\"  executor=\"tomcatThreadPool\"  URIEncoding=\"UTF-8\"/\u0026gt;  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EAJP端口，默认8009，如下改,8010\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;Connector port=\"8010\" protocol=\"AJP/1.3\" redirectPort=\"8443\" /\u0026gt;  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-配置不同的jdk\" class=\"anchor\" href=\"#3-%E9%85%8D%E7%BD%AE%E4%B8%8D%E5%90%8C%E7%9A%84jdk\"\u003E\u003C/a\u003E3. 配置不同的JDK\u003C/h3\u003E\n\u003Cp\u003E修改tomcat环境变量有三种方法：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E第一种：定义在全局里；如果装有多个JDK的话，定义全局会冲突，不建议\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E第二种：写用户家目录下的环境变量文件.bash_profile\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E第三种：是定义在单个tomcat的启动和关闭程序里，建议使用这种\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@Tomcat ~]# vim /usr/local/tomcat/bin/startup.sh              --tomcat的启动程序\n[root@Tomcat ~]# vim /usr/local/tomcat/bin/shutdown.sh             --tomcat的关闭程序\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E把startup.sh和shutdown.sh这两个脚本里的最前面加上下面一段：\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eexport JAVA_HOME=/usr/local/java\nexport TOMCAT_HOME=/usr/local/tomcat\nexport CATALINA_HOME=/usr/local/tomcat\nexport CLASS_PATH=$JAVA_HOME/bin/lib:$JAVA_HOME/jre/lib:$JAVA_HOME/lib/tool.jar\nexport PATH=$PATH:/usr/local/java/bin:/usr/local/tomcat/bin\n\n\n\u003C/code\u003E\u003C/pre\u003E","987033":"\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E编辑/etc/gdm/custom.conf文件并保存退出(允许root用户通过177端口远程访问xdmcp桌面服务):\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@vm205 ~]# cp /etc/gdm/custom.conf /etc/gdm/custom.conf.bak\n[root@vm205 ~]# vi /etc/gdm/custom.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003E----------在[xdmcp]选项下添加如下一行内容----------\nEnable=true\nPort=177\n----------在[security]选项下添加如下一行内容------\nAllowRemoteRoot=true\n------------------------------------------------\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E查看刚才修改内容\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@vm205 ~]# grep -Ev '^#' /etc/gdm/custom.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E重启gdm服务(在Linux6系统中没有gdm-restart之类的命令了---注意区别):\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ereboot\n\u003C/code\u003E\u003C/pre\u003E","1137948":"\u003Ch3\u003E\n\u003Ca id=\"1压缩\" class=\"anchor\" href=\"#1%E5%8E%8B%E7%BC%A9\"\u003E\u003C/a\u003E1.压缩\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E打包成xxx.tar（即tarfile）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -cvf xxx.tar xxx ... (多个目录)\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar进行打包压缩成xxx.tar.gz\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zcvf xxx.tar.gz xxx ...(多个目录)　　\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-解包\" class=\"anchor\" href=\"#2-%E8%A7%A3%E5%8C%85\"\u003E\u003C/a\u003E2. 解包\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解包xxx.tar\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -xvf xxx.tar\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar解压缩xxx.tar.gz文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf xxx.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar解压缩xxx.tar.gz文件到指定的目录(该目录需已经存在)\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf xxx.tar.gz -C destdir\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用tar解压缩xxx.tar.gz中某个文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf xxx.tar.gz aaa/bbb\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-查看压缩包内的内容\" class=\"anchor\" href=\"#3-%E6%9F%A5%E7%9C%8B%E5%8E%8B%E7%BC%A9%E5%8C%85%E5%86%85%E7%9A%84%E5%86%85%E5%AE%B9\"\u003E\u003C/a\u003E3. 查看压缩包内的内容\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -ztvf xxx.tar.gz\n\u003C/code\u003E\u003C/pre\u003E","1174238":"\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.ext.face.excel;\n\nimport com.sun.image.codec.jpeg.JPEGImageEncoder;\nimport com.sun.image.codec.jpeg.JPEGCodec;\nimport com.sun.image.codec.jpeg.JPEGEncodeParam;\n\nimport javax.imageio.ImageIO;\nimport java.awt.image.BufferedImage;\nimport java.text.SimpleDateFormat;\nimport java.util.*;\nimport java.io.File;\nimport java.io.IOException;\nimport java.io.FileOutputStream;\n\npublic class ResizeImage {\n\n    private final static SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    /**\n     * @param im            原始图像\n     * @param resizeTimes   需要缩小的倍数，缩小2倍为原来的1/2 ，这个数值越大，返回的图片越小\n     * @return              返回处理后的图像\n     */\n    public BufferedImage resizeImage(BufferedImage im, float resizeTimes) {\n        /*原始图像的宽度和高度*/\n        int width = im.getWidth();\n        int height = im.getHeight();\n\n        /*调整后的图片的宽度和高度*/\n        int toWidth = (int) (Float.parseFloat(String.valueOf(width)) / resizeTimes);\n        int toHeight = (int) (Float.parseFloat(String.valueOf(height)) / resizeTimes);\n\n        /*新生成结果图片*/\n        BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);\n\n        result.getGraphics().drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);\n        return result;\n    }\n\n    /**\n     * @param im            原始图像\n     * @param resizeTimes   倍数,比如0.5就是缩小一半,0.98等等double类型\n     * @return              返回处理后的图像\n     */\n    public BufferedImage zoomImage(BufferedImage im, float resizeTimes) {\n        /*原始图像的宽度和高度*/\n        int width = im.getWidth();\n        int height = im.getHeight();\n\n        /*调整后的图片的宽度和高度*/\n        int toWidth = (int) (Float.parseFloat(String.valueOf(width)) * resizeTimes);\n        int toHeight = (int) (Float.parseFloat(String.valueOf(height)) * resizeTimes);\n\n        /*新生成结果图片*/\n        BufferedImage result = new BufferedImage(toWidth, toHeight, BufferedImage.TYPE_INT_RGB);\n\n        result.getGraphics().drawImage(im.getScaledInstance(toWidth, toHeight, java.awt.Image.SCALE_SMOOTH), 0, 0, null);\n        return result;\n    }\n\n    /**\n     * @param path  要转化的图像的文件夹,就是存放图像的文件夹路径\n     * @param type  图片的后缀名组成的数组\n     * @return\n     */\n    public List\u0026lt;BufferedImage\u0026gt; getImageList(String path, String[] type) throws IOException{\n        Map\u0026lt;String,Boolean\u0026gt; map = new HashMap\u0026lt;String, Boolean\u0026gt;();\n        for(String s : type) {\n            map.put(s,true);\n        }\n        List\u0026lt;BufferedImage\u0026gt; result = new ArrayList\u0026lt;BufferedImage\u0026gt;();\n        File[] fileList = new File(path).listFiles();\n        for (File f : fileList) {\n            if(f.length() == 0)\n                continue;\n            if(map.get(getExtension(f.getName())) == null)\n                continue;\n            result.add(javax.imageio.ImageIO.read(f));\n        }\n        return result;\n    }\n\n    /**\n     * 把图片写到磁盘上\n     * @param im\n     * @param path     eg: C://home// 图片写入的文件夹地址\n     * @param fileName DCM1987.jpg  写入图片的名字\n     * @return\n     */\n    public boolean writeToDisk(BufferedImage im, String path, String fileName) {\n        File f = new File(path + fileName);\n        String fileType = getExtension(fileName);\n        if (fileType == null)\n            return false;\n        try {\n            ImageIO.write(im, fileType, f);\n            im.flush();\n            return true;\n        } catch (IOException e) {\n            return false;\n        }\n    }\n\n\n    public boolean writeHighQuality(BufferedImage im, String fileFullPath) {\n        try {\n            /*输出到文件流*/\n            FileOutputStream newimage = new FileOutputStream(fileFullPath+System.currentTimeMillis()+\".jpg\");\n            JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(newimage);\n            JPEGEncodeParam jep = JPEGCodec.getDefaultJPEGEncodeParam(im);\n            /* 压缩质量 */\n            jep.setQuality(1f, true);\n            encoder.encode(im, jep);\n            /*近JPEG编码*/\n            newimage.close();\n            return true;\n        } catch (Exception e) {\n            return false;\n        }\n    }\n\n    /**\n     * 返回文件的文件后缀名\n     * @param fileName\n     * @return\n     */\n    public String getExtension(String fileName) {\n        try {\n            return fileName.split(\"\\\\.\")[fileName.split(\"\\\\.\").length - 1];\n        } catch (Exception e) {\n            return null;\n        }\n    }\n\n    public static void main(String[] args) throws Exception{\n\n        long start = System.currentTimeMillis();\n\n        /*这儿填写你存放要缩小图片的文件夹全地址*/\n        String inputFoler = \"D:\\\\5i84\\\\2018\\\\人脸识别\\\\人脸照片\\\\采集原图\\\\12-19\";\n\n        /*这儿填写你转化后的图片存放的文件夹*/\n        String outputFolder = \"D:\\\\5i84\\\\2018\\\\人脸识别\\\\人脸照片\\\\采集原图\\\\12-19\\\\outPut\\\\1\";\n\n\n        /*这个参数是要转化成的倍数,如果是1就是转化成1倍*/\n        float times = 0.05f;\n\n\n        ResizeImage r = new ResizeImage();\n        List\u0026lt;BufferedImage\u0026gt; imageList = r.getImageList(inputFoler,new String[] {\"jpg\"});\n        for(BufferedImage i : imageList) {\n            r.writeHighQuality(r.zoomImage(i,times),outputFolder);\n        }\n\n        System.out.println(\"处理结束：\" + FORMAT.format(new Date()) + \"  耗时：\" + (System.currentTimeMillis() - start) / 1000 + \"s\");\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E","831356":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EServer 端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.io.IOException;\nimport java.net.ServerSocket;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class Server {\n\n\n    public static void main(String[] args) {\n\n        ServerSocket serverSocket = null;\n\n        try {\n            serverSocket = new ServerSocket(Constants.PORT);\n            System.out.println(\"======================  服务启动  =======================\");\n            Socket socket = serverSocket.accept();\n\n            /**\n             * 单独启动线程处理\n             */\n//            new Thread(new SocketHandler(socket)).start();\n\n            /**\n             * 利用线程池处理\n             */\n            HandlerExecutorPool executorPool = new HandlerExecutorPool(100, 20);\n            executorPool.execute(new SocketHandler(socket));\n\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            SocketUtils.close(serverSocket);\n        }\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ESocketHandler\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.PrintWriter;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class SocketHandler implements Runnable {\n\n    private Socket socket;\n\n    public SocketHandler(Socket socket) {\n        this.socket = socket;\n    }\n\n    @Override\n    public void run() {\n        BufferedReader reader = null;\n        PrintWriter writer = null;\n\n        try {\n            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));\n            writer = new PrintWriter(socket.getOutputStream(), true);\n\n            String msg = null;\n            while (true) {\n                msg = reader.readLine();\n                if (msg == null) {\n                    break;\n                }\n\n                System.out.println(\"接收到信息： \" + msg);\n                writer.println(\"服务器端回送响的应数据.\");\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            SocketUtils.close(reader, writer, socket);\n        }\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EClient 端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.PrintWriter;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class Client {\n\n    public static void  main(String[] args) {\n\n        Socket socket = null ;\n        BufferedReader reader = null;\n        PrintWriter writer = null;\n\n        try {\n            socket = new Socket(Constants.HOST , Constants.PORT);\n            reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));\n            writer = new PrintWriter(socket.getOutputStream(), true);\n\n\n            writer.println(\"客户端发送信息: 123\");\n\n            String msg = null ;\n            while (true) {\n                msg = reader.readLine();\n                if (msg == null) {\n                    break;\n                }\n                System.out.println(\"客户端收到信息:\" + msg);\n            }\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            SocketUtils.close(reader, writer, socket);\n        }\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E线程池方式处理\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport java.util.concurrent.ArrayBlockingQueue;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.ThreadPoolExecutor;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/18\n */\npublic class HandlerExecutorPool {\n\n    private ExecutorService executorService;\n\n    public HandlerExecutorPool(int maxSize, int queueSize) {\n        this.executorService = new ThreadPoolExecutor(\n                Runtime.getRuntime().availableProcessors() - 1,\n                            maxSize, 120L, TimeUnit.SECONDS, new ArrayBlockingQueue\u0026lt;\u0026gt;(queueSize));\n    }\n\n\n    public void execute(Runnable runnable) {\n        this.executorService.execute(runnable);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ESocketUtils\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.PrintWriter;\nimport java.net.ServerSocket;\nimport java.net.Socket;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/10/17\n */\npublic class SocketUtils {\n\n\n    /**\n     * 关闭资源\n     *\n     * @param reader\n     * @param writer\n     * @param socket\n     */\n    public static void close(BufferedReader reader, PrintWriter writer, Socket socket) {\n        if (reader != null) {\n            try {\n                reader.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n        if (writer != null) {\n            try {\n                writer.close();\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n\n        if (socket != null) {\n            try {\n                socket.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n\n        socket = null;\n    }\n\n    public static void close(ServerSocket serverSocket) {\n        if (serverSocket != null) {\n            try {\n                serverSocket.close();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n\n        serverSocket = null;\n    }\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EConstants\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Constants {\n\n    public static final String HOST = \"127.0.0.1\";\n\n    public static final int PORT = 8333;\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-说明\" class=\"anchor\" href=\"#2-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用线程池可以减少服务器开销\u003C/li\u003E\n\u003Cli\u003E三次握手过程：\n\u003Col class=\"task-list\"\u003E\n\u003Cli\u003EserverSocket 启动监听\u003C/li\u003E\n\u003Cli\u003Eclient 发起连接\u003C/li\u003E\n\u003Cli\u003Eserver 确认连接\u003C/li\u003E\n\u003Cli\u003Eclient 确认连接\u003C/li\u003E\n\u003Cli\u003EC/S 通信\u003C/li\u003E\n\u003C/ol\u003E\n\u003C/li\u003E\n\u003C/ul\u003E","996034":"\u003Ch3\u003E\n\u003Ca id=\"java-堆\" class=\"anchor\" href=\"#java-%E5%A0%86\"\u003E\u003C/a\u003EJAVA 堆\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1115/105158_15c413f4_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1老年代三分之二的堆空间\" class=\"anchor\" href=\"#1%E8%80%81%E5%B9%B4%E4%BB%A3%E4%B8%89%E5%88%86%E4%B9%8B%E4%BA%8C%E7%9A%84%E5%A0%86%E7%A9%BA%E9%97%B4\"\u003E\u003C/a\u003E1、老年代：三分之二的堆空间\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E老生代采用的回收算法是标记整理算法\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2新生代--三分之一的堆空间\" class=\"anchor\" href=\"#2%E6%96%B0%E7%94%9F%E4%BB%A3--%E4%B8%89%E5%88%86%E4%B9%8B%E4%B8%80%E7%9A%84%E5%A0%86%E7%A9%BA%E9%97%B4\"\u003E\u003C/a\u003E2、新生代 ： 三分之一的堆空间\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eeden区： 8/10 的年轻代空间\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Esurvivor0 : 1/10 的年轻代空间\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Esurvivor1 : 1/10 的年轻代空间\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E新生代的回收机制采用复制算法，当我们的对象时长超过一定年龄时（默认15，可以通过参数设置），将会把对象放入老生代\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E对象刚实例化出来的时候分配在eden区\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E在一次新生代回收后，如果对象还存活，则会进入S0或S1区，之后每进过一次新生代回收，如果对象存活则他的回收次数就会加1\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当回收次数达到一定阈值时，则进入老年代\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3参数配置\" class=\"anchor\" href=\"#3%E5%8F%82%E6%95%B0%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3、参数配置\u003C/h4\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E作用\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:InitialSurvivorRatio\u003C/td\u003E\n\u003Ctd\u003E新生代Eden/Survivor空间的初始比例\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:Newratio\u003C/td\u003E\n\u003Ctd\u003EOld区 和 Yong区 的内存比例\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","1013230":"\u003Ch3\u003E\n\u003Ca id=\"1-算法介绍\" class=\"anchor\" href=\"#1-%E7%AE%97%E6%B3%95%E4%BB%8B%E7%BB%8D\"\u003E\u003C/a\u003E1. 算法介绍\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E引用计数法：引用计数+1，失去引用-1；这种方法有一严重问题：无法处理循环引用情况，每次加减会浪费系统性能\u003C/li\u003E\n\u003Cli\u003E标记清除法：分标记和清除两个步骤，最大弊端是回收后导致内存空间不连续\u003C/li\u003E\n\u003Cli\u003E标记压缩法：在标记清除法的基础上，把存活对象压缩到内存的一端（老年代的垃圾回收算法）\u003C/li\u003E\n\u003Cli\u003E复制算法：把存活的对象复制到另外一块区域，然后清除原先的区域（新生代的垃圾回收算法）\u003C/li\u003E\n\u003Cli\u003E分代\u003C/li\u003E\n\u003Cli\u003E分区\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-为啥新生代与老年代的算法不一致\" class=\"anchor\" href=\"#2-%E4%B8%BA%E5%95%A5%E6%96%B0%E7%94%9F%E4%BB%A3%E4%B8%8E%E8%80%81%E5%B9%B4%E4%BB%A3%E7%9A%84%E7%AE%97%E6%B3%95%E4%B8%8D%E4%B8%80%E8%87%B4\"\u003E\u003C/a\u003E2. 为啥新生代与老年代的算法不一致\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E新生代回收频率高、对象不稳定，每次GC耗时短\u003C/li\u003E\n\u003Cli\u003E新生代回收的对象比较多\u003C/li\u003E\n\u003Cli\u003E老年代的对象是经过多次GC存活下来的，可能是长期存活的，回收频率低，耗时长，应尽量减少老年代的GC\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/093326_c9101443_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/095614_b2a2aaea_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/102011_c965df0e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1119/110141_a5a54c6b_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","1165108":"\u003Ch3\u003E\n\u003Ca id=\"1-单独jar\" class=\"anchor\" href=\"#1-%E5%8D%95%E7%8B%ACjar\"\u003E\u003C/a\u003E1. 单独jar\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;plugins\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;spring-boot-maven-plugin\u0026lt;/artifactId\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n\u0026lt;/plugins\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-资源lib分开\" class=\"anchor\" href=\"#2-%E8%B5%84%E6%BA%90lib%E5%88%86%E5%BC%80\"\u003E\u003C/a\u003E2. 资源、lib分开\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;build\u0026gt;\n      \n\n\u0026lt;finalName\u0026gt;face\u0026lt;/finalName\u0026gt;\n\u0026lt;resources\u0026gt;\n    \u0026lt;resource\u0026gt;\n\t\u0026lt;directory\u0026gt;src/main/resources\u0026lt;/directory\u0026gt;\n    \u0026lt;/resource\u0026gt;\n    \u0026lt;resource\u0026gt;\n\t\u0026lt;directory\u0026gt;src/main/webapp\u0026lt;/directory\u0026gt;\n    \u0026lt;/resource\u0026gt;\n\u0026lt;/resources\u0026gt;\n\n\u0026lt;plugins\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-compiler-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t    \u0026lt;source\u0026gt;${java.version}\u0026lt;/source\u0026gt;\n\t    \u0026lt;target\u0026gt;${java.version}\u0026lt;/target\u0026gt;\n\t    \u0026lt;encoding\u0026gt;UTF-8\u0026lt;/encoding\u0026gt;\n\t\u0026lt;/configuration\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;org.apache.maven.plugins\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-dependency-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t    \u0026lt;execution\u0026gt;\n\t\t\u0026lt;id\u0026gt;copy-dependencies\u0026lt;/id\u0026gt;\n\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\u0026lt;goals\u0026gt;\n\t\t    \u0026lt;goal\u0026gt;copy-dependencies\u0026lt;/goal\u0026gt;\n\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;configuration\u0026gt;\n\t\t    \u0026lt;outputDirectory\u0026gt;${project.build.directory}/lib\u0026lt;/outputDirectory\u0026gt;\n\t\t\u0026lt;/configuration\u0026gt;\n\t    \u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n    \u0026lt;!-- 打成jar包 --\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-jar-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t    \u0026lt;excludes\u0026gt;\n\t\t\u0026lt;exclude\u0026gt;**/*.properties\u0026lt;/exclude\u0026gt;\n\t\t\u0026lt;exclude\u0026gt;**/pages/**\u0026lt;/exclude\u0026gt;\n\t\t\u0026lt;exclude\u0026gt;**/static/**\u0026lt;/exclude\u0026gt;\n\t    \u0026lt;/excludes\u0026gt;\n\t    \u0026lt;archive\u0026gt;\n\t\t\u0026lt;manifest\u0026gt;\n\t\t    \u0026lt;addClasspath\u0026gt;true\u0026lt;/addClasspath\u0026gt;\n\t\t    \u0026lt;classpathPrefix\u0026gt;lib/\u0026lt;/classpathPrefix\u0026gt;\n\t\t    \u0026lt;!--指明main方法所在的类 --\u0026gt;\n\t\t    \u0026lt;mainClass\u0026gt;com.xlauch.ext.face.FaceDetectApplication\u0026lt;/mainClass\u0026gt;\n\t\t    \u0026lt;useUniqueVersions\u0026gt;false\u0026lt;/useUniqueVersions\u0026gt;\n\t\t\u0026lt;/manifest\u0026gt;\n\t\t\u0026lt;manifestEntries\u0026gt;\n\t\t    \u0026lt;Class-Path\u0026gt;config/\u0026lt;/Class-Path\u0026gt;\n\t\t\u0026lt;/manifestEntries\u0026gt;\n\t    \u0026lt;/archive\u0026gt;\n\t\u0026lt;/configuration\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n    \u0026lt;!-- 处理资源文件 --\u0026gt;\n    \u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;org.apache.maven.plugins\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;maven-resources-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;version\u0026gt;2.4\u0026lt;/version\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t    \u0026lt;execution\u0026gt;\n\t\t\u0026lt;id\u0026gt;copy-resources\u0026lt;/id\u0026gt;\n\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\u0026lt;goals\u0026gt;\n\t\t    \u0026lt;goal\u0026gt;copy-resources\u0026lt;/goal\u0026gt;\n\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;configuration\u0026gt;\n\t\t    \u0026lt;encoding\u0026gt;utf-8\u0026lt;/encoding\u0026gt;\n\t\t    \u0026lt;outputDirectory\u0026gt;${project.build.directory}/config\u0026lt;/outputDirectory\u0026gt;\n\t\t    \u0026lt;!--把配置文件拷到/etc路径下 --\u0026gt;\n\t\t    \u0026lt;resources\u0026gt;\n\t\t\t\u0026lt;resource\u0026gt;\n\t\t\t    \u0026lt;directory\u0026gt;src/main/resources/\u0026lt;/directory\u0026gt;\n\t\t\t    \u0026lt;includes\u0026gt;\n\t\t\t\t\u0026lt;include\u0026gt;**/*.properties\u0026lt;/include\u0026gt;\n\t\t\t    \u0026lt;/includes\u0026gt;\n\t\t\t\u0026lt;/resource\u0026gt;\n\t\t\t\u0026lt;resource\u0026gt;\n\t\t\t    \u0026lt;directory\u0026gt;src/main/webapp/\u0026lt;/directory\u0026gt;\n\t\t\t    \u0026lt;includes\u0026gt;\n\t\t\t\t\u0026lt;include\u0026gt;**/pages/**\u0026lt;/include\u0026gt;\n\t\t\t\t\u0026lt;include\u0026gt;**/static/**\u0026lt;/include\u0026gt;\n\t\t\t    \u0026lt;/includes\u0026gt;\n\t\t\t\u0026lt;/resource\u0026gt;\n\t\t    \u0026lt;/resources\u0026gt;\n\t\t\u0026lt;/configuration\u0026gt;\n\t    \u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n    \u0026lt;/plugin\u0026gt;\n\u0026lt;/plugins\u0026gt;\n\u0026lt;/build\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E","1340233":"\u003Cp\u003E.keep\u003C/p\u003E","1060681":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/jaycekon/p/6225058.html\"\u003EJava消息队列--ActiveMq 初体验\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"http://activemq.apache.org/\"\u003EActiveMq 官网\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-下载安装\" class=\"anchor\" href=\"#2-%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. 下载安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EActiveMQ官网下载地址：\u003Ca href=\"http://activemq.apache.org/download.html\"\u003Ehttp://activemq.apache.org/download.html\u003C/a\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1128/141923_d9755b78_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Col class=\"task-list\"\u003E\n\u003Cli\u003Ebin存放的是脚本文件\u003C/li\u003E\n\u003Cli\u003Econf存放的是基本配置文件\u003C/li\u003E\n\u003Cli\u003Edata存放的是日志文件\u003C/li\u003E\n\u003Cli\u003Edocs存放的是说明文档\u003C/li\u003E\n\u003Cli\u003Eexamples存放的是简单的实例\u003C/li\u003E\n\u003Cli\u003Elib存放的是activemq所需jar包\u003C/li\u003E\n\u003Cli\u003Ewebapps用于存放项目的目录\u003C/li\u003E\n\u003C/ol\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-启动activemq\" class=\"anchor\" href=\"#3-%E5%90%AF%E5%8A%A8activemq\"\u003E\u003C/a\u003E3. 启动ActiveMQ　\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost apache-activemq-5.15.8]$ cd bin/\n[fxz@localhost bin]$ ./activemq start\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-访问\" class=\"anchor\" href=\"#4-%E8%AE%BF%E9%97%AE\"\u003E\u003C/a\u003E4. 访问\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EActiveMQ默认启动时，启动了内置的jetty服务器，提供一个用于监控ActiveMQ的admin应用。 \n\nadmin：http://127.0.0.1:8161/admin/\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1128/142322_f1e4a454_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E　　我们在浏览器打开链接之后输入账号密码（这里和tomcat 服务器类似）\u003C/p\u003E\n\u003Cp\u003E　　默认账号：admin\u003C/p\u003E\n\u003Cp\u003E　　密码：admin\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-停止activemq\" class=\"anchor\" href=\"#5-%E5%81%9C%E6%AD%A2activemq\"\u003E\u003C/a\u003E5. 停止ActiveMQ　\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost apache-activemq-5.15.8]$ cd bin/\n[fxz@localhost bin]$ ./activemq stop\n\u003C/code\u003E\u003C/pre\u003E","1214593":"\u003Ch3\u003E\n\u003Ca id=\"1创建模板maven工程\" class=\"anchor\" href=\"#1%E5%88%9B%E5%BB%BA%E6%A8%A1%E6%9D%BFmaven%E5%B7%A5%E7%A8%8B\"\u003E\u003C/a\u003E1、创建模板maven工程\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/102924_e7ded36f_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E根据实际需求创建\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"11-工程创建好之后--需要在pom文件中添加创建骨架的插件\" class=\"anchor\" href=\"#11-%E5%B7%A5%E7%A8%8B%E5%88%9B%E5%BB%BA%E5%A5%BD%E4%B9%8B%E5%90%8E--%E9%9C%80%E8%A6%81%E5%9C%A8pom%E6%96%87%E4%BB%B6%E4%B8%AD%E6%B7%BB%E5%8A%A0%E5%88%9B%E5%BB%BA%E9%AA%A8%E6%9E%B6%E7%9A%84%E6%8F%92%E4%BB%B6\"\u003E\u003C/a\u003E1.1 工程创建好之后 , 需要在pom文件中添加创建骨架的插件.\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;plugin\u0026gt;\n    \u0026lt;groupId\u0026gt;org.apache.maven.plugins\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;maven-archetype-plugin\u0026lt;/artifactId\u0026gt;\n    \u0026lt;version\u0026gt;3.0.0\u0026lt;/version\u0026gt;\n\u0026lt;/plugin\u0026gt; \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-执行命令\" class=\"anchor\" href=\"#2-%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E2. 执行命令\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"21-生成archetype\" class=\"anchor\" href=\"#21-%E7%94%9F%E6%88%90archetype\"\u003E\u003C/a\u003E2.1 生成archetype\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E执行命令: archetype:create-from-project\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/103511_6b84e352_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E执行完毕后，会在target下生成archetype目录\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/103720_cc432cc6_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"22-安装install\" class=\"anchor\" href=\"#22-%E5%AE%89%E8%A3%85install\"\u003E\u003C/a\u003E2.2 安装install\u003C/h4\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/104000_d888bf0e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"23-执行archetypecrawl\" class=\"anchor\" href=\"#23-%E6%89%A7%E8%A1%8Carchetypecrawl\"\u003E\u003C/a\u003E2.3 执行archetype:crawl\u003C/h4\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/111024_737f3fbd_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E执行完毕，会在本地私仓生成archetype-catalog.xml\nE:\\deve\\tools\\apache-maven-3.3.9\\repository\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/111157_d0da6ce9_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-使用自己的骨架\" class=\"anchor\" href=\"#3-%E4%BD%BF%E7%94%A8%E8%87%AA%E5%B7%B1%E7%9A%84%E9%AA%A8%E6%9E%B6\"\u003E\u003C/a\u003E3. 使用自己的骨架\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1229/111317_4e2e2767_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-删除骨架\" class=\"anchor\" href=\"#4-%E5%88%A0%E9%99%A4%E9%AA%A8%E6%9E%B6\"\u003E\u003C/a\u003E4. 删除骨架\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ewindows下面的：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003EC:\\Users\\wang.IntelliJIdea2018.1\\system\\Maven\\Indices\\UserArchetypes.xml \u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003ELinux和mac的可以参见：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/yirentianran/article/details/52232523\"\u003Ehttps://blog.csdn.net/yirentianran/article/details/52232523\u003C/a\u003E\u003C/p\u003E","990608":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Eset key value\u003C/td\u003E\n\u003Ctd\u003E设置指定 key 的值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Eget key\u003C/td\u003E\n\u003Ctd\u003E获取指定 key 的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Egetrange key start end\u003C/td\u003E\n\u003Ctd\u003E返回 key 中字符串值的子字符\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Egetset key value\u003C/td\u003E\n\u003Ctd\u003E将给定 key 的值设为 value ，并返回 key 的旧值(old value)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Egetbit key offset\u003C/td\u003E\n\u003Ctd\u003E对 key 所储存的字符串值，获取指定偏移量上的位(bit)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Emget key1 [key2..]\u003C/td\u003E\n\u003Ctd\u003E获取所有(一个或多个)给定 key 的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Esetbit key offset value\u003C/td\u003E\n\u003Ctd\u003E对 key 所储存的字符串值，设置或清除指定偏移量上的位(bit)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Esetex key seconds value\u003C/td\u003E\n\u003Ctd\u003E将值 value 关联到 key ，并将 key 的过期时间设为 seconds (以秒为单位)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Esetnx key value\u003C/td\u003E\n\u003Ctd\u003E只有在 key 不存在时设置 key 的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Esetrange key offset value\u003C/td\u003E\n\u003Ctd\u003E用 value 参数覆写给定 key 所储存的字符串值，从偏移量 offset 开始。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Estrlen key\u003C/td\u003E\n\u003Ctd\u003E返回 key 所储存的字符串值的长度。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Emset key value [key value ...]\u003C/td\u003E\n\u003Ctd\u003E同时设置一个或多个 key-value 对。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Emsetnx key value [key value ...]\u003C/td\u003E\n\u003Ctd\u003E同时设置一个或多个 key-value 对，当且仅当所有给定 key 都不存在。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Epsetex key milliseconds value\u003C/td\u003E\n\u003Ctd\u003E这个命令和 setex 命令相似，但它以毫秒为单位设置 key 的生存时间，而不是像 setex 命令那样，以秒为单位。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Eincr key\u003C/td\u003E\n\u003Ctd\u003E将 key 中储存的数字值增一。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Eincrby key increment\u003C/td\u003E\n\u003Ctd\u003E将 key 所储存的值加上给定的增量值（increment） 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E17\u003C/td\u003E\n\u003Ctd\u003Eincrbyfloat key increment\u003C/td\u003E\n\u003Ctd\u003E将 key 所储存的值加上给定的浮点增量值（increment） 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E18\u003C/td\u003E\n\u003Ctd\u003Edecr key\u003C/td\u003E\n\u003Ctd\u003E将 key 中储存的数字值减一。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E19\u003C/td\u003E\n\u003Ctd\u003Edecrby key decrement\u003C/td\u003E\n\u003Ctd\u003Ekey 所储存的值减去给定的减量值（decrement） 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E20\u003C/td\u003E\n\u003Ctd\u003Eappend key value\u003C/td\u003E\n\u003Ctd\u003E如果 key 已经存在并且是一个字符串， append 命令将指定的 value 追加到该 key 原来值（value）的末尾。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","1024028":"\u003Ch3\u003E\n\u003Ca id=\"1-准备三个redis服务masterslave1slave2\" class=\"anchor\" href=\"#1-%E5%87%86%E5%A4%87%E4%B8%89%E4%B8%AAredis%E6%9C%8D%E5%8A%A1masterslave1slave2\"\u003E\u003C/a\u003E1. 准备三个redis服务，master,slave1,slave2.\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1修改redisconf-配置\" class=\"anchor\" href=\"#1%E4%BF%AE%E6%94%B9redisconf-%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E（1）修改redis.conf 配置\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Emaster配置：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 设置端口\nport 6000\n\n# 设置密码\nrequirepass 123456\n\n# 修改主机ip\nbind 192.168.222.132 127.0.0.1\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eslave1、slave2修改配置：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eport 6001\nrequirepass 123456\n \n# 配置master的ip port\nslaveof 127.0.0.1 6000\n# 配置master的密码\nmasterauth 123456\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2启动服务\" class=\"anchor\" href=\"#2%E5%90%AF%E5%8A%A8%E6%9C%8D%E5%8A%A1\"\u003E\u003C/a\u003E（2）启动服务\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动master\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# cd /usr/local/redis-4.0.11/src\n[root@localhost src]# ./redis-server ../redis.conf\n[root@localhost src]# ./redis-cli \n127.0.0.1:6379\u0026gt; info\n\n\n# Replication  由于从服务器还没启动，所以看到的slave数量为0\nrole:master\nconnected_slaves:0\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动slave1、slave2\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# cd /usr/local/redis-4.0.11/src\n[root@localhost src]# ./redis-server ../redis.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E验证\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# ./redis-cli\n[root@localhost src]# info\n\n# Replication \nrole:master\nconnected_slaves:2\nslave0:ip=192.168.222.133,port=6379,state=online,offset=1832,lag=1\nslave1:ip=192.168.222.134,port=6379,state=online,offset=1832,lag=0\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E可以在master上set key，然后在slave上get key，测试能否同步取到\u003C/p\u003E","1047683":"\u003Ch3\u003E\n\u003Ca id=\"1-命令\" class=\"anchor\" href=\"#1-%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 命令\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster info\u003C/td\u003E\n\u003Ctd\u003E打印集群的信息\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster nodes\u003C/td\u003E\n\u003Ctd\u003E列出集群当前已知的所有节点信息\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster meet  \u003C/td\u003E\n\u003Ctd\u003E将 ip 和 port 所指定的节点添加到集群当中，让它成为集群的一份子。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster forget \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E从集群中移除 node_id 指定的节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster replicate \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E将当前节点设置为 node_id 指定的节点的从节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster saveconfig\u003C/td\u003E\n\u003Ctd\u003E将节点的配置文件保存到硬盘里面。槽(slot)\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster addslots  [slot ...]\u003C/td\u003E\n\u003Ctd\u003E将一个或多个槽（ slot）指派（ assign）给当前节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster delslots  [slot ...]\u003C/td\u003E\n\u003Ctd\u003E移除一个或多个槽对当前节点的指派。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster flushslots\u003C/td\u003E\n\u003Ctd\u003E移除指派给当前节点的所有槽，让当前节点变成一个没有指派任何槽的节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  node \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E将槽 slot 指派给 node_id 指定的节点，如果槽已经指派给另一个节点，那么先让另一个节点删除该槽\u0026gt;，然后再进行指派。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  migrating \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E将本节点的槽 slot 迁移到 node_id 指定的节点中。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  importing \u0026lt;node_id\u0026gt;\u003C/td\u003E\n\u003Ctd\u003E从 node_id 指定的节点中导入槽 slot 到本节点。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster setslot  stable\u003C/td\u003E\n\u003Ctd\u003E取消对槽 slot 的导入（ import）或者迁移（ migrate）。键\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster keyslot \u003C/td\u003E\n\u003Ctd\u003E计算键 key 应该被放置在哪个槽上。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster countkeysinslot \u003C/td\u003E\n\u003Ctd\u003E返回槽 slot 目前包含的键值对数量。\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003Ecluster getkeysinslot  \u003C/td\u003E\n\u003Ctd\u003E返回 count 个 slot 槽中的键\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","1129838":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/fanyongbin/p/5699482.html\"\u003EOracle 12c创建PDB用户并设置默认表空间\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-创建pdb数据库\" class=\"anchor\" href=\"#2-%E5%88%9B%E5%BB%BApdb%E6%95%B0%E6%8D%AE%E5%BA%93\"\u003E\u003C/a\u003E2. 创建PDB数据库\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E选择Database Configuration Assistant\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1213/152034_56ab7765_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E设置全局数据库名及PDB名\n\u003Cimg src=\"https://static.oschina.net/uploads/img/201812/13094942_9g8X.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E- CDB名：xlauch\n- PDB名：xlauch_db\n- 管理口令：Xlauch123456\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201812/13095810_FpkD.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201812/13101927_mCyn.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-创建表空间\" class=\"anchor\" href=\"#3-%E5%88%9B%E5%BB%BA%E8%A1%A8%E7%A9%BA%E9%97%B4\"\u003E\u003C/a\u003E3. 创建表空间\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 创建临时表空间\ncreate temporary tablespace i84_temp\ntempfile 'E:\\deve\\db\\oracle\\tablespace\\i84_temp.dbf'\nsize 32m\nautoextend on\nnext 32m MAXSIZE unlimited  \nextent management local;\n\n# 创建数据表空间\ncreate tablespace i84_data\nlogging\ndatafile 'E:\\deve\\db\\oracle\\tablespace\\i84_data.dbf'\nsize 100m\nautoextend on\nnext 50m MAXSIZE unlimited  \nextent management local;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-创建用户\" class=\"anchor\" href=\"#4-%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7\"\u003E\u003C/a\u003E4. 创建用户\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecreate user xlauch identified by xlauch \ndefault tablespace i84_data  \ntemporary tablespace i84_temp;\n\n# 用户授权\ngrant create session,resource,dba to xlauch;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-配置tnsname\" class=\"anchor\" href=\"#5-%E9%85%8D%E7%BD%AEtnsname\"\u003E\u003C/a\u003E5. 配置tnsname\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Ei84 =\n  (DESCRIPTION =\n    (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))\n    (CONNECT_DATA =\n      (SERVER = DEDICATED)\n      (SERVICE_NAME = xlauch_db)\n    )\n  )\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-使用plsql-连接\" class=\"anchor\" href=\"#6-%E4%BD%BF%E7%94%A8plsql-%E8%BF%9E%E6%8E%A5\"\u003E\u003C/a\u003E6. 使用pl/SQL 连接\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1213/152540_83e584cc_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","679412":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 对象锁的同步和异步问题\n * @author alienware\n *\n */\npublic class MyObject {\n\n\tpublic synchronized void method1(){\n\t\ttry {\n\t\t\tSystem.out.println(Thread.currentThread().getName());\n\t\t\tThread.sleep(4000);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\n\t/** synchronized */\n\tpublic void method2(){\n\t\t\tSystem.out.println(Thread.currentThread().getName());\n\t}\n\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal MyObject mo = new MyObject();\n\t\t\n\t\t/**\n\t\t * 分析：\n\t\t * t1线程先持有object对象的Lock锁，t2线程可以以异步的方式调用对象中的非synchronized修饰的方法\n\t\t * t1线程先持有object对象的Lock锁，t2线程如果在这个时候调用对象中的同步（synchronized）方法则需等待，也就是同步\n\t\t */\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmo.method1();\n\t\t\t}\n\t\t},\"t1\");\n\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmo.method2();\n\t\t\t}\n\t\t},\"t2\");\n\n\t\tt1.start();\n\t\tt2.start();\n\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"method2\"方法不加synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/114534_c60b6ece_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"method2\"方法加上synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/114707_838e195a_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-案例说明\" class=\"anchor\" href=\"#2-%E6%A1%88%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 案例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，t2线程可以以异步的方式调用对象中的非synchronized修饰的方法\u003C/li\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，t2线程如果在这个时候调用对象中的同步（synchronized）方法则需等待，也就是同步\u003C/li\u003E\n\u003C/ul\u003E","688447":"\u003Ch3\u003E\n\u003Ca id=\"1-示例\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8B\"\u003E\u003C/a\u003E1 示例\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ConnThreadLocal {\n\n\tpublic static ThreadLocal\u0026lt;String\u0026gt; th = new ThreadLocal\u0026lt;String\u0026gt;();\n\t\n\tpublic void setTh(String value){\n\t\tth.set(value);\n\t}\n\tpublic void getTh(){\n\t\tSystem.out.println(Thread.currentThread().getName() + \":\" + this.th.get());\n\t}\n\t\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\t\n\t\tfinal ConnThreadLocal ct = new ConnThreadLocal();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tct.setTh(\"张三\");\n\t\t\t\tct.getTh();\n\t\t\t}\n\t\t}, \"t1\");\n\t\t\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\ttry {\n\t\t\t\t\tThread.sleep(1000);\n\t\t\t\t\tct.getTh();\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t}\n\t\t}, \"t2\");\n\t\t\n\t\tt1.start();\n\t\tt2.start();\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E","698153":"\u003Ch3\u003E\n\u003Ca id=\"1-concurrentlinkedqueue-高性能无阻塞无界队列\" class=\"anchor\" href=\"#1-concurrentlinkedqueue-%E9%AB%98%E6%80%A7%E8%83%BD%E6%97%A0%E9%98%BB%E5%A1%9E%E6%97%A0%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E1. ConcurrentLinkedQueue 高性能无阻塞无界队列\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E//高性能无阻塞无界队列：ConcurrentLinkedQueue\nConcurrentLinkedQueue\u0026lt;String\u0026gt; q = new ConcurrentLinkedQueue\u0026lt;String\u0026gt;();\nq.offer(\"a\");\nq.offer(\"b\");\nq.offer(\"c\");\nq.offer(\"d\");\nq.add(\"e\");\n\nSystem.out.println(q.poll());\t//a 从头部取出元素，并从队列里删除\nSystem.out.println(q.size());\t//4\nSystem.out.println(q.peek());\t//b\nSystem.out.println(q.size());\t//4\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E因为在Queeue中定义了\"add\"与\"offer\"方法，在ConcurrentListQueeue中两个方法一致无区别\u003C/li\u003E\n\u003Cli\u003E\"poll\"方法：获取首个元素并删除\u003C/li\u003E\n\u003Cli\u003E\"add\"方法：获取首个元素不删除\u003C/li\u003E\n\u003Cli\u003E\"FIFO\" 规则\u003C/li\u003E\n\u003Cli\u003E元素不允许为null\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-arrayblockingqueue-数组阻塞有界队列\" class=\"anchor\" href=\"#2-arrayblockingqueue-%E6%95%B0%E7%BB%84%E9%98%BB%E5%A1%9E%E6%9C%89%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E2. ArrayBlockingQueue 数组阻塞有界队列\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EArrayBlockingQueue\u0026lt;String\u0026gt; array = new ArrayBlockingQueue\u0026lt;String\u0026gt;(5);\narray.put(\"a\");\narray.put(\"b\");\narray.add(\"c\");\narray.add(\"d\");\narray.add(\"e\");\narray.add(\"f\");\n//System.out.println(array.offer(\"a\", 3, TimeUnit.SECONDS));\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E声明时候需指定容量\u003C/li\u003E\n\u003Cli\u003E\"offer\"方法：可以延迟添加，返回是否添加成功\u003C/li\u003E\n\u003Cli\u003E没有实现读写分离，无法进行并行操作\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-linkedblockingqueue-链式阻塞队列\" class=\"anchor\" href=\"#3-linkedblockingqueue-%E9%93%BE%E5%BC%8F%E9%98%BB%E5%A1%9E%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E3. LinkedBlockingQueue 链式阻塞队列\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003ELinkedBlockingQueue\u0026lt;String\u0026gt; q = new LinkedBlockingQueue\u0026lt;String\u0026gt;();\nq.offer(\"a\");\nq.offer(\"b\");\nq.offer(\"c\");\nq.offer(\"d\");\nq.offer(\"e\");\nq.add(\"f\");\n\nSystem.out.println(q);\n\nList\u0026lt;String\u0026gt; list = new ArrayList\u0026lt;String\u0026gt;();\nSystem.out.println(q.drainTo(list, 3));\nSystem.out.println(list.size());\nfor (String string : list) {\n System.out.println(string);\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以指定容量：new LinkedBlockingQueue(5);\u003C/li\u003E\n\u003Cli\u003E内部实现分离锁（读写两把锁），可以实现生产与消费并行\u003C/li\u003E\n\u003Cli\u003E无界队列，内部有链式缓冲区\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4synchronousqueue-同步\" class=\"anchor\" href=\"#4synchronousqueue-%E5%90%8C%E6%AD%A5\"\u003E\u003C/a\u003E4.SynchronousQueue 同步\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Efinal SynchronousQueue\u0026lt;String\u0026gt; q = new SynchronousQueue\u0026lt;String\u0026gt;();\nThread t1 = new Thread(new Runnable() {\n    @Override\n    public void run() {\n        try {\n            System.out.println(q.take());\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n});\nt1.start();\nThread t2 = new Thread(new Runnable() {\n    \n    @Override\n    public void run() {\n        q.add(\"asdasd\");\n    }\n});\nt2.start();\t\t\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E需先执行take操作，才能执行add操作\u003C/li\u003E\n\u003Cli\u003E本身队列不存放元素，只是把数据转发\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5priorityblockingqueue-优先级队列\" class=\"anchor\" href=\"#5priorityblockingqueue-%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E5.PriorityBlockingQueue 优先级队列\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Etask 类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Task implements Comparable\u0026lt;Task\u0026gt;{\n\t\n\tprivate int id ;\n\tprivate String name;\n\tpublic int getId() {\n\t\treturn id;\n\t}\n\tpublic void setId(int id) {\n\t\tthis.id = id;\n\t}\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\t\n\t@Override\n\tpublic int compareTo(Task task) {\n\t\treturn this.id \u0026gt; task.id ? 1 : (this.id \u0026lt; task.id ? -1 : 0);  \n\t}\n\t\n\tpublic String toString(){\n\t\treturn this.id + \",\" + this.name;\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class UsePriorityBlockingQueue {\n\n\t\n\tpublic static void main(String[] args) throws Exception{\n\t\t\n\t\t\n\t\tPriorityBlockingQueue\u0026lt;Task\u0026gt; q = new PriorityBlockingQueue\u0026lt;Task\u0026gt;();\n\t\t\n\t\tTask t1 = new Task();\n\t\tt1.setId(3);\n\t\tt1.setName(\"id为3\");\n\t\tTask t2 = new Task();\n\t\tt2.setId(4);\n\t\tt2.setName(\"id为4\");\n\t\tTask t3 = new Task();\n\t\tt3.setId(1);\n\t\tt3.setName(\"id为1\");\n\t\t\n\t\t//return this.id \u0026gt; task.id ? 1 : 0;\n\t\tq.add(t1);\t//3\n\t\tq.add(t2);\t//4\n\t\tq.add(t3);  //1\n\t\t\n\t\t// 1 3 4\n\t\tSystem.out.println(\"容器：\" + q);\n\t\tSystem.out.println(q.take().getId());\n\t\tSystem.out.println(\"容器：\" + q);\n//\t\tSystem.out.println(q.take().getId());\n//\t\tSystem.out.println(q.take().getId());\n\t\t\n\n\t\t\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E元素必须实现\"Comparable\"接口\u003C/li\u003E\n\u003Cli\u003E添加元素不排序，take时进行排序\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6delayqueue-延迟带时间队列\" class=\"anchor\" href=\"#6delayqueue-%E5%BB%B6%E8%BF%9F%E5%B8%A6%E6%97%B6%E9%97%B4%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E6.DelayQueue 延迟带时间队列\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EWangmin 类\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Wangmin implements Delayed {\n\n    private String name;\n    //身份证  \n    private String id;\n    //截止时间  \n    private long endTime;\n    //定义时间工具类\n    private TimeUnit timeUnit = TimeUnit.SECONDS;\n\n    public Wangmin(String name, String id, long endTime) {\n        this.name = name;\n        this.id = id;\n        this.endTime = endTime;\n    }\n\n    public String getName() {\n        return this.name;\n    }\n\n    public String getId() {\n        return this.id;\n    }\n\n    /**\n     * 用来判断是否到了截止时间\n     */\n    @Override\n    public long getDelay(TimeUnit unit) {\n        //return unit.convert(endTime, TimeUnit.MILLISECONDS) - unit.convert(System.currentTimeMillis(), TimeUnit.MILLISECONDS);\n        return endTime - System.currentTimeMillis();\n    }\n\n    /**\n     * 相互批较排序用\n     */\n    @Override\n    public int compareTo(Delayed delayed) {\n        Wangmin w = (Wangmin) delayed;\n        return this.getDelay(this.timeUnit) - w.getDelay(this.timeUnit) \u0026gt; 0 ? 1 : 0;\n    }\n\n\n}  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003E\npublic class WangBa implements Runnable {  \n    \n    private DelayQueue\u0026lt;Wangmin\u0026gt; queue = new DelayQueue\u0026lt;Wangmin\u0026gt;();  \n    \n    public boolean yinye =true;  \n      \n    public void shangji(String name,String id,int money){  \n        Wangmin man = new Wangmin(name, id, 1000 * money + System.currentTimeMillis());  \n        System.out.println(\"网名\"+man.getName()+\" 身份证\"+man.getId()+\"交钱\"+money+\"块,开始上机...\");  \n        this.queue.add(man);  \n    }  \n      \n    public void xiaji(Wangmin man){  \n        System.out.println(\"网名\"+man.getName()+\" 身份证\"+man.getId()+\"时间到下机...\");  \n    }  \n  \n    @Override  \n    public void run() {  \n        while(yinye){  \n            try {  \n                Wangmin man = queue.take();  \n                xiaji(man);  \n            } catch (InterruptedException e) {  \n                e.printStackTrace();  \n            }  \n        }  \n    }  \n      \n    public static void main(String args[]){  \n        try{  \n            System.out.println(\"网吧开始营业\");  \n            WangBa siyu = new WangBa();  \n            Thread shangwang = new Thread(siyu);  \n            shangwang.start();  \n              \n            siyu.shangji(\"路人甲\", \"123\", 1);  \n            siyu.shangji(\"路人乙\", \"234\", 10);  \n            siyu.shangji(\"路人丙\", \"345\", 5);  \n        }  \n        catch(Exception e){  \n            e.printStackTrace();\n        }  \n  \n    }  \n}  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E元素需实现\"Delayed\"接口\u003C/li\u003E\n\u003Cli\u003E无界队列，有读写锁\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0828/094434_9dbced71_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","748709":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/11\n */\npublic class TestFuture implements Callable\u0026lt;String\u0026gt; {\n\n    private static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    private String param;\n\n    public TestFuture(String param) {\n        this.param = param;\n    }\n\n    @Override\n    public String call() throws Exception {\n        Thread.sleep(2000);\n        return format.format(new Date()) + \"  \" + param + \" 执行结束\";\n    }\n\n\n    /**\n     * @param args\n     */\n    public static void main(String[] args) throws Exception {\n        ExecutorService executorService = Executors.newFixedThreadPool(2);\n\n        System.out.println(format.format(new Date()) + \" 开始执行\");\n\n        FutureTask\u0026lt;String\u0026gt; futureTask1 = new FutureTask\u0026lt;String\u0026gt;(new TestFuture(\"张三\"));\n        FutureTask\u0026lt;String\u0026gt; futureTask2 = new FutureTask\u0026lt;String\u0026gt;(new TestFuture(\"李四\"));\n\n        // 当future.get() == null 时表示执行完成\n        Future f1 = executorService.submit(futureTask1);\n        // 如果此处调用future.get()，那么主线程将阻塞直到执行完毕\n//        System.out.println(f1.get());\n        Future f2 = executorService.submit(futureTask2);\n\n        // 执行点其它事情\n        System.out.println(\"执行点其它事情\");\n        Thread.sleep(1500);\n\n        // 获取执行结果\n        System.out.println(futureTask1.get());\n        System.out.println(futureTask2.get());\n\n        System.out.println(format.format(new Date()) + \" 执行结束\");\n        executorService.shutdown();\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0911/170129_2e945d2e_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以实现线程并行\u003C/li\u003E\n\u003C/ul\u003E","821414":"\u003Ch3\u003E\n\u003Ca id=\"1disruptor示例demo\" class=\"anchor\" href=\"#1disruptor%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1.Disruptor示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建disruptor\n * @param eventFactory      ： 创建事件工厂\n * @param ringBufferSize    ： ringbuffer大小 ，必须是2的N次方\n * @param executor          :  线程池\n * @param producerType      :  生产者类型\n *                                  ProducerType.SINGLE：单个生产者\n *                                  ProducerType.MULTI: 多个生产者\n * @param waitStrategy      :  等待策略\n *                                  BlockingWaitStrategy 是最低效的策略，但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现\n *                                  SleepingWaitStrategy 的性能表现跟BlockingWaitStrategy差不多，对CPU的消耗也类似，但其对生产者线程的影响最小，适合用于异步日志类似的场景\n *                                  YieldingWaitStrategy 的性能是最好的，适合用于低延迟的系统。在要求极高性能且事件处理线数小于CPU逻辑核心数的场景中，推荐使用此策略；例如，CPU开启超线程的特性\n */\nDisruptor\u0026lt;UserEvent\u0026gt; disruptor = new Disruptor\u0026lt;UserEvent\u0026gt;(eventFactory, ringBufferSize, executor, ProducerType.SINGLE, new YieldingWaitStrategy());\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EEvent            : 事件对象，可以理解生产者和消费者交互过程中，传输的对象，一般POJO\u003C/li\u003E\n\u003Cli\u003EEventFactory     : 事件工厂，在disruptor初始化时，需要在往ringbuffer中创建初始化事件对象\u003C/li\u003E\n\u003Cli\u003EEventProducer    : 事件生产者，用于发布事件，先从ringbuffer中获取为被使用的初始对象，进行加工，然后发布出去\u003C/li\u003E\n\u003Cli\u003ERingBuffer       : 事件缓存地方：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-通俗理解不一定贴切\" class=\"anchor\" href=\"#2-%E9%80%9A%E4%BF%97%E7%90%86%E8%A7%A3%E4%B8%8D%E4%B8%80%E5%AE%9A%E8%B4%B4%E5%88%87\"\u003E\u003C/a\u003E2. 通俗理解（不一定贴切）\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EEvent            : 牛奶盒\u003C/li\u003E\n\u003Cli\u003EEventFactory     : 生产空的牛奶盒、放到生产线\u003C/li\u003E\n\u003Cli\u003ERingBuffer       : 生产线，上面流转着等待灌装的空的牛奶盒\u003C/li\u003E\n\u003Cli\u003EEventProducer    : 从生产线拿走一个空的牛奶盒，注入牛奶，卖个客人\u003C/li\u003E\n\u003Cli\u003EDisruptor        : 生产车间\u003C/li\u003E\n\u003C/ul\u003E","987034":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"http://blog.netsarang.com/89/connecting-to-centos-7/\"\u003Exmanager 连接centos7\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-安装\" class=\"anchor\" href=\"#2-%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. 安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装epel源\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install epel-release\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E切换到root用户\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esu root\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装lightdm\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install lightdm\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改配置文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecp lightdm.conf  lightdm.conf.bak\nvim /etc/lightdm/lightdm.conf\n\n# 配置内容：\n[XDMCPServer]\nenabled=false\nport=177\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改CentOS7默认的显示管理器为lightdm，命令为：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esystemctl disable gdm \n\nsystemctl enable lightdm\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动lightdm，命令为：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esystemctl stop gdm\nsystemctl start lightdm\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关闭防火墙\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esystemctl stop firewalld.service\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E以yum方式继续安装xfce轻量级桌面环境，命令为：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum groupinstall xfce\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在Windows上打开Xstart，输入各项配置信息和命令（/usr/bin/xfce4-session），点击运行即可远程连接CentOS7，如图：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1031/100006_b2b71368_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","987049":"\u003Col class=\"task-list\"\u003E\n\u003Cli\u003E查看文件权限设置\u003C/li\u003E\n\u003C/ol\u003E\n\u003Cpre\u003E\u003Ccode\u003E//查看/bin/bash文件的权限\nls -al /bin/bash\n//结果如下\n-rwxr-xr-x 1 root root 938736 Apr 23  2012 /bin/bash\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E第1位给出了该项的属性，即是文件还是目录，或者是链接文件等。\u003C/li\u003E\n\u003Cli\u003E-：表示是文件，如上面的案例就是一个文件；\u003C/li\u003E\n\u003Cli\u003Ed：表示是目录；\u003C/li\u003E\n\u003Cli\u003El：表示是链接文件。\u003C/li\u003E\n\u003Cli\u003E第2、3、4位给出了文件或目录所有者的权限。\u003C/li\u003E\n\u003Cli\u003E第5、6、7位给出了文件或目录所属用户组的权限。\u003C/li\u003E\n\u003Cli\u003E第8、9、10位给出了其他用户权限。\u003C/li\u003E\n\u003Cli\u003Er：为读权限。\u003C/li\u003E\n\u003Cli\u003Ew：为写权限。\u003C/li\u003E\n\u003Cli\u003Ex：为执行权限。目录的执行权限的意思是可以用cd命令进入该目录\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E2、chmod命令：该命令用来修改文件或目录的访问权限。\u003C/p\u003E\n\u003Cp\u003E第一种方式为：chmod a+r 文件或目录名\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E其中a可用u、g、o替换，+可用=、-替换，r可用w、x替换\u003C/li\u003E\n\u003Cli\u003Ea：表示修改所有用户的权限。包括u、g、o\u003C/li\u003E\n\u003Cli\u003Eu：表示只给文件或目录所有者修改权限\u003C/li\u003E\n\u003Cli\u003Eg：表示给文件所有组修改权限\u003C/li\u003E\n\u003Cli\u003Eo：表示给其他用户修改权限\u003C/li\u003E\n\u003Cli\u003E+：表示增加某种权限\u003C/li\u003E\n\u003Cli\u003E-：表示减去某种权限\u003C/li\u003E\n\u003Cli\u003E=：表示赋予某种权限\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E第二种方式为：用数字表示权限，r：用4表示 w：用2表示 x：用1表示\n则1~7表示的权限如下：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1：–x\u003C/li\u003E\n\u003Cli\u003E2:：-w-\u003C/li\u003E\n\u003Cli\u003E3：-wx\u003C/li\u003E\n\u003Cli\u003E4：r–\u003C/li\u003E\n\u003Cli\u003E5：r-x\u003C/li\u003E\n\u003Cli\u003E6：rw-\u003C/li\u003E\n\u003Cli\u003E7：rwx\u003C/li\u003E\n\u003Cli\u003E于是可用“chmod 777 文件或目录名”命令来修改权限。三个7中第一个代表所有者权限，第二个代表所有组权限，第三个代表其他用户权限。当然，也可用类似于“chmod u+2文件目录名”的方式来修改权限。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E附：\n实例一：将/usr/local/test目录及其子目录的读、写、执行权限开放给所有用户\u003C/p\u003E\n\u003Cp\u003E-R表示修改当前目录及其子目录，不加-R仅修改当前目录\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Echmod -R 777 /usr/local/test \n\u003C/code\u003E\u003C/pre\u003E","1184536":"\u003Ch3\u003E\n\u003Ca id=\"1-引入pomxml\" class=\"anchor\" href=\"#1-%E5%BC%95%E5%85%A5pomxml\"\u003E\u003C/a\u003E1. 引入pom.xml\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;dependency\u0026gt;\n    \u0026lt;groupId\u0026gt;net.coobird\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;thumbnailator\u0026lt;/artifactId\u0026gt;\n    \u0026lt;version\u0026gt;0.4.8\u0026lt;/version\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-测试demo\" class=\"anchor\" href=\"#2-%E6%B5%8B%E8%AF%95demo\"\u003E\u003C/a\u003E2. 测试demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.ext.face.excel;\n\n\nimport net.coobird.thumbnailator.Thumbnails;\n\nimport java.io.File;\nimport java.io.IOException;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/12/22\n */\npublic class ResizeImage2 {\n\n    /**\n     * @param standardImgPath 原图片path\n     * @param thumName        缩略图path\n     */\n    private static String storeThumbnail(String standardImgPath, String thumName) {\n        File file = new File(standardImgPath);\n        if (file != null \u0026amp;\u0026amp; file.isFile()) {\n            try {\n                File outFIle = new File(thumName);\n                Thumbnails.of(file).scale(0.2f).toFile(outFIle);\n                return outFIle.getName();\n            } catch (IOException e) {\n                e.printStackTrace();\n            }\n        }\n        return null;\n    }\n\n\n    public static void main(String[] args) {\n        storeThumbnail(\"C:\\\\Users\\\\dell\\\\Desktop\\\\error\\\\24270.jpg\", \"C:\\\\Users\\\\dell\\\\Desktop\\\\error\\\\24270_0.jpg\");\n    }\n\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E","1003739":"\u003Ch3\u003E\n\u003Ca id=\"1-参数说明\" class=\"anchor\" href=\"#1-%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 参数说明\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E说明\u003C/th\u003E\n\u003Cth\u003E默认配置\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xms\u003C/td\u003E\n\u003Ctd\u003E初始堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmx\u003C/td\u003E\n\u003Ctd\u003E最大堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmn\u003C/td\u003E\n\u003Ctd\u003E配置新生代大小，对系统性能及GC有比较大影响，一般配置在堆大小的1/4到1/3左右\u003C/td\u003E\n\u003Ctd\u003E1/3\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:NewRatio\u003C/td\u003E\n\u003Ctd\u003E老年代/新生代\u003C/td\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:SurvivorRatio\u003C/td\u003E\n\u003Ctd\u003EEden区/Form区的比例=EDEN/FROM=EDEN/TO\u003C/td\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintCommandLineFlags\u003C/td\u003E\n\u003Ctd\u003E输出参数信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGC\u003C/td\u003E\n\u003Ctd\u003E打印GC日志\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGCDetails\u003C/td\u003E\n\u003Ctd\u003E打印GC日志详细信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E提示：可以把初始化堆的大小设置成最大堆的大小，这样可以减少程序运行时垃圾回收的次数，从而提高性能\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例一\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E4%B8%80\"\u003E\u003C/a\u003E2. 示例一\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.xlauch.jvm;\n\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * -Xms5m -Xmx20m -XX:+PrintCommandLineFlags -XX:+PrintGC -XX:+PrintGCDetails\n *\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/11/16\n */\npublic class Test1 {\n\n    /**\n     * 1M 大小\n     */\n    private static final int M_SIZE = 1 * 1024 * 1024;\n\n\n    public static void main(String[] args) {\n        printRunTimeMsg();\n        // 分配1m内存\n        byte[] bytes = new byte[M_SIZE];\n        printRunTimeMsg();\n\n        // 分配3m内存\n        byte[] bytes2 = new byte[3 * M_SIZE];\n        printRunTimeMsg();\n    }\n\n\n    /**\n     * 打印jvm内存信息\n     */\n    private static void printRunTimeMsg() {\n        System.out.println(\"\\n===========================================================\");\n        System.out.println(\"最大内存：\" + getSize(Runtime.getRuntime().maxMemory()));\n        System.out.println(\"初始内存：\" + getSize(Runtime.getRuntime().totalMemory()));\n        System.out.println(\"空闲内存：\" + getSize(Runtime.getRuntime().freeMemory()));\n    }\n\n    /**\n     * 转为M单位\n     *\n     * @param size\n     * @return\n     */\n    private static long getSize(long size) {\n        return size / M_SIZE;\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1116/140412_5f82c927_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","1015490":"\u003Ch4\u003E\n\u003Ca id=\"1-串行回收器\" class=\"anchor\" href=\"#1-%E4%B8%B2%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8\"\u003E\u003C/a\u003E1. 串行回收器\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-XX:+UseSerialGC\u003C/li\u003E\n\u003Cli\u003E新生代、老年代都可以使用\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-并行回收器\" class=\"anchor\" href=\"#2-%E5%B9%B6%E8%A1%8C%E5%9B%9E%E6%94%B6%E5%99%A8\"\u003E\u003C/a\u003E2. 并行回收器\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-XX:+UseParNewGC\u003C/li\u003E\n\u003Cli\u003E串行回收器的多线程化\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-cms回收器标记清除\" class=\"anchor\" href=\"#3-cms%E5%9B%9E%E6%94%B6%E5%99%A8%E6%A0%87%E8%AE%B0%E6%B8%85%E9%99%A4\"\u003E\u003C/a\u003E3. CMS回收器(标记清除）\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E-XX:+UseConcMaskSweepGC\u003C/li\u003E\n\u003Cli\u003E-XX:ConcGCThreads： 线程数量\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4-g1回收器分区算法\" class=\"anchor\" href=\"#4-g1%E5%9B%9E%E6%94%B6%E5%99%A8%E5%88%86%E5%8C%BA%E7%AE%97%E6%B3%95\"\u003E\u003C/a\u003E4. G1回收器（分区算法）\u003C/h4\u003E","1340234":"\u003Ch4\u003E\n\u003Ca id=\"1-克隆代码\" class=\"anchor\" href=\"#1-%E5%85%8B%E9%9A%86%E4%BB%A3%E7%A0%81\"\u003E\u003C/a\u003E1. 克隆代码\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit clone https://github.com/dubbo/dubbo-ops.git\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-修改applicationproperties配置信息\" class=\"anchor\" href=\"#2-%E4%BF%AE%E6%94%B9applicationproperties%E9%85%8D%E7%BD%AE%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E2. 修改\"application.properties\"配置信息\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eserver.port=7001\nspring.velocity.cache=false\nspring.velocity.charset=UTF-8\nspring.velocity.layout-url=/templates/default.vm\nspring.messages.fallback-to-system-locale=false\nspring.messages.basename=i18n/message\nspring.root.password=root\nspring.guest.password=guest\n\ndubbo.registry.address=zookeeper://127.0.0.1:2181\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E注意：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eserver.port：访问端口\u003C/li\u003E\n\u003Cli\u003Espring.root.password ： root 用户密码\u003C/li\u003E\n\u003Cli\u003Espring.guest.password ：guest 用户密码\u003C/li\u003E\n\u003Cli\u003Edubbo.registry.address：zookeeper 注册地址\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-编译打包\" class=\"anchor\" href=\"#3-%E7%BC%96%E8%AF%91%E6%89%93%E5%8C%85\"\u003E\u003C/a\u003E3. 编译打包\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Emvn clean package\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4-启动控制台\" class=\"anchor\" href=\"#4-%E5%90%AF%E5%8A%A8%E6%8E%A7%E5%88%B6%E5%8F%B0\"\u003E\u003C/a\u003E4. 启动控制台\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003EE:\\deve\\workspace\\dubbo\\code\\dubbo-ops\\dubbo-admin\\target\u0026gt; java -jar .\\dubbo-admin-0.0.1-SNAPSHOT.jar\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"5-访问-httplocalhost7001\" class=\"anchor\" href=\"#5-%E8%AE%BF%E9%97%AE-httplocalhost7001\"\u003E\u003C/a\u003E5. 访问 \u003Ca href=\"http://localhost:7001/\"\u003Ehttp://localhost:7001/\u003C/a\u003E\n\u003C/h4\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2019/0227/152339_f06b97ff_907621.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E","995328":"\u003Ch3\u003E\n\u003Ca id=\"redis-哈希hash\" class=\"anchor\" href=\"#redis-%E5%93%88%E5%B8%8Chash\"\u003E\u003C/a\u003Eredis 哈希(hash)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis hash 是一个string类型的field和value的映射表，hash特别适合用于存储对象。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 中每个 hash 可以存储 2^32 - 1 键值对（40多亿）。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Ehdel key field1 [field2]\u003C/td\u003E\n\u003Ctd\u003E删除一个或多个哈希表字段\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ehexists key field\u003C/td\u003E\n\u003Ctd\u003E查看哈希表 key 中，指定的字段是否存在。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Ehget key field\u003C/td\u003E\n\u003Ctd\u003E获取存储在哈希表中指定字段的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Ehgetall key\u003C/td\u003E\n\u003Ctd\u003E获取在哈希表中指定 key 的所有字段和值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Ehincrby key field increment\u003C/td\u003E\n\u003Ctd\u003E为哈希表 key 中的指定字段的整数值加上增量 increment 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ehincrbyfloat key field increment\u003C/td\u003E\n\u003Ctd\u003E为哈希表 key 中的指定字段的浮点数值加上增量 increment 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Ehkeys key\u003C/td\u003E\n\u003Ctd\u003E获取所有哈希表中的字段\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ehlen key\u003C/td\u003E\n\u003Ctd\u003E获取哈希表中字段的数量\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Ehmget key field1 [field2]\u003C/td\u003E\n\u003Ctd\u003E获取所有给定字段的值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Ehmset key field1 value1 [field2 value2 ]\u003C/td\u003E\n\u003Ctd\u003E同时将多个 field-value (域-值)对设置到哈希表 key 中。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Ehset key field value\u003C/td\u003E\n\u003Ctd\u003E将哈希表 key 中的字段 field 的值设为 value 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Ehsetnx key field value\u003C/td\u003E\n\u003Ctd\u003E只有在字段 field 不存在时，设置哈希表字段的值。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Ehvals key\u003C/td\u003E\n\u003Ctd\u003E获取哈希表中所有值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Ehscan key cursor [match pattern] [count count]\u003C/td\u003E\n\u003Ctd\u003E迭代哈希表中的键值对。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","1024354":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/kerwinC/p/6069864.html\"\u003Eredis主从+哨兵模式\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"https://segmentfault.com/a/1190000002680804\"\u003ERedis Sentinel机制与用法\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1修改sentinelconf-配置\" class=\"anchor\" href=\"#1%E4%BF%AE%E6%94%B9sentinelconf-%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E（1）修改sentinel.conf 配置\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E复制sentinel.conf 配置文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-4.0.11]# cd /usr/local/redis-4.0.11/\n[root@localhost redis-4.0.11]# cp sentinel.conf sentinel.conf.bakcp sentinel.conf sentinel.conf.bak\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改sentinel.conf 配置\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /opt/redis/conf/sentinel.conf\n\n##sentinel for  10.0.0.10 ,its slave is 10.0.0.20\n#master1\n\n# 配置哨兵端口号\nport 26383\n\ndir /usr/local/redis-4.0.11/sentinel-dir\n\n# sentinel monitor 监控的master的名称 ip 端口 确认master死亡所需哨兵的个数\nsentinel monitor master1 192.168.222.132 6379 2\n\n# \nsentinel down-after-milliseconds master1 30000\nsentinel failover-timeout master1 120000\nsentinel parallel-syncs master1 1\n#sentinel auth-pass mymaster 123456　　#如果你的redis集群有密码\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关闭相关防火墙，或者开放端口\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Ca href=\"https://gitee.com/efrans/dashboard/wikis/efrans%2Fsb?doc_id=154819\u0026amp;sort_id=1024065\"\u003Ecentos7 设置防火墙\u003C/a\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动 Sentinel\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eredis-sentinel /path/to/sentinel.conf\n\n或者\n\nredis-server /path/to/sentinel.conf --sentinel\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003EMaster-\u0026gt;Slave-\u0026gt;Sentinel,要确保按照这个顺序依次启动。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3配置说明\" class=\"anchor\" href=\"#3%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E（3）配置说明\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel monitor mymaster 127.0.0.1 6379 2\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003E这一行代表sentinel监控的master的名字叫做mymaster,地址为127.0.0.1:6379，行尾最后的一个2代表什么意思呢？我们知道，网络是不可靠的，有时候一个sentinel会因为网络堵塞而误以为一个master redis已经死掉了，当sentinel集群式，解决这个问题的方法就变得很简单，只需要多个sentinel互相沟通来确认某个master是否真的死了，这个2代表，当集群中有2个sentinel认为master死了时，才能真正认为该master已经不可用了。（sentinel集群中各个sentinel也有互相通信，通过gossip协议）。\u003C/p\u003E\n\u003C/blockquote\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel down-after-milliseconds master1 30000\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003Esentinel会向master发送心跳PING来确认master是否存活，如果master在“一定时间范围”内不回应PING 或者是回复了一个错误消息，那么这个sentinel会主观地(单方面地)认为这个master已经不可用了(subjectively down, 也简称为SDOWN)。而这个down-after-milliseconds就是用来指定这个“一定时间范围”的，单位是毫秒。\u003C/p\u003E\n\u003C/blockquote\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel failover-timeout master1 900000\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003E如果sentinel A推荐sentinel B去执行failover，A等待一段时间后再去failover, 因为根据上下文是B failover timeout了, 之后A再去进行一次。\u003C/p\u003E\n\u003C/blockquote\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Esentinel parallel-syncs master1 1\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cblockquote\u003E\n\u003Cp\u003E在发生failover主备切换时，这个选项指定了最多可以有多少个slave同时对新的master进行同步，这个数字越小，完成failover所需的时间就越长，但是如果这个数字越大，就意味着越多的slave因为replication而不可用。可以通过将这个值设为 1 来保证每次只有一个slave处于不能处理命令请求的状态\u003C/p\u003E\n\u003C/blockquote\u003E","1048315":"\u003Ch3\u003E\n\u003Ca id=\"1-集群操作脚本\" class=\"anchor\" href=\"#1-%E9%9B%86%E7%BE%A4%E6%93%8D%E4%BD%9C%E8%84%9A%E6%9C%AC\"\u003E\u003C/a\u003E1. 集群操作脚本\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E#!/bin/bash\n\n# 配置节点信息\nNODES=(\n  192.168.222.129:7001\n  192.168.222.129:7002\n  192.168.222.129:7003\n  192.168.222.129:7004\n  192.168.222.129:7005\n  192.168.222.129:7006\n)\n\n# Redis 主目录\nREDIS_HOME=/usr/local/deve/soft/redis-4.0.11\n\n# Redis-Cluster 集群主目录\nREDIS_CLUSTER_HOME=/usr/local/deve/soft/redis-cluster\n\n# 当前路径\nPWD=`pwd`\n\n# 启动集群\nstart_cluster(){\n  echo \"==================================== 启动集群 =====================================\"\n  for str in ${NODES[@]};do\n    arr=(${str//:/ })\n    \n    echo \"启动节点 $str\"\n    ${REDIS_HOME}/src/redis-server ${REDIS_CLUSTER_HOME}/${arr[1]}/redis.conf\n  done\n\n  echo \"==================================== 启动成功 =====================================\"  \n    ps -ef | grep redis\n}\n\n# 停止集群\nstop_cluster(){\n  echo \"==================================== 停止集群 =====================================\"\n  for str in ${NODES[@]};do\n    arr=(${str//:/ })\n    \n    echo \"停止节点 $str\"\n    ${REDIS_HOME}/src/redis-cli -c -h ${arr[0]} -p ${arr[1]} shutdown\n  done\n\n  echo \"==================================== 停止成功 =====================================\"  \n    ps -ef | grep redis\n}\n\n\n\n# 清除集群\nclear_cluster(){\n    echo \"=========================== 清除集群开始 ===============\"\n   \n  for str in ${NODES[@]};do\n    arr=(${str//:/ })\n    \n    echo \"停止节点 $str\"\n    ${REDIS_HOME}/src/redis-cli -c -h ${arr[0]} -p ${arr[1]} shutdown\n  \n        echo \"备份节点 $str\"\n        echo `mv ${PWD}/${arr[1]}/node*.conf -f ${PWD}/bak/`\n        echo `mv ${PWD}/${arr[1]}/*.rdb -f ${PWD}/bak/`\n        echo `mv ${PWD}/${arr[1]}/*.aof -f ${PWD}/bak/`\n    done\n\n\n    echo \"=========================== 清除集群成功 ===============\"\n    ps -ef | grep redis\n}\n\n\n# 重建集群\nbuild_cluster(){\n  echo \"启动集群\"\n  start_cluster    \n    \n    echo \"==================================== 重建集群 =====================================\"\n    /usr/local/deve/soft/redis-4.0.11/src/redis-trib.rb  create  --replicas 1 ${NODES[*]} \n    echo \"==================================== 重建成功 =====================================\"  \n    \n  ps -ef | grep redis\n}\n\n\n# 接收输入\nif [[ $1 = 'start' ]];\nthen\n  start_cluster\nelif [[ $1 = 'stop' ]] || [[ $1 = 'shutdown' ]];\nthen\n  stop_cluster\n\nelif [[ $1 = 'clear' ]] || [[ $1 = 'delete' ]];\nthen\n  clear_cluster\n\nelif [[ $1 = 'build' ]] ;\nthen\n  build_cluster\n\nelif [[ $1 = '7001' ]] || [[ $1 = '7002' ]]|| [[ $1 = '7003' ]]|| [[ $1 = '7004' ]]|| [[ $1 = '7005' ]]|| [[ $1 = '7006' ]];\nthen\n  \n  /usr/local/deve/soft/redis-4.0.11/src/redis-cli -c -h 192.168.222.129  -p $1\n\nelse\n  echo \"=========================== 相关命令 ===============\"\n    echo \"build         重建集群\"\n    echo \"clear         删除集群\"\n    echo \"stop          停止集群\"\n    echo \"start         启动集群\"\n    echo \"700*          启动客户端\"\n    echo \"====================================================\"\n\nfi\n\u003C/code\u003E\u003C/pre\u003E","1059881":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.cnblogs.com/xymBlog/p/9303032.html\"\u003E最简单版本(先看这篇)\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/plei_yue/article/details/79362372\"\u003ESpringBoot(六)：SpringBoot整合Redis\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/baidu_41669919/article/details/79148203\"\u003Eredis学习系列(二)--spring boot整合Redis集群\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-pomxml-添加依赖\" class=\"anchor\" href=\"#2-pomxml-%E6%B7%BB%E5%8A%A0%E4%BE%9D%E8%B5%96\"\u003E\u003C/a\u003E2. pom.xml 添加依赖\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;dependency\u0026gt;\n   \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt;\n   \u0026lt;artifactId\u0026gt;spring-boot-starter-data-redis\u0026lt;/artifactId\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-配置applicationproperties\" class=\"anchor\" href=\"#3-%E9%85%8D%E7%BD%AEapplicationproperties\"\u003E\u003C/a\u003E3. 配置application.properties\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 配置redis\nspring.redis.cluster.nodes=192.168.222.129:7001,192.168.222.129:7002,192.168.222.129:7003,192.168.222.129:7004,192.168.222.129:7005,192.168.222.129:7006\nspring.redis.cluster.max-redirects=100\nspring.redis.cluster.timeout=10000\nspring.redis.jedis.pool.max-active=1000\nspring.redis.jedis.pool.max-idle=30\nspring.redis.jedis.pool.min-idle=5\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-编写config\" class=\"anchor\" href=\"#4-%E7%BC%96%E5%86%99config\"\u003E\u003C/a\u003E4. 编写config\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.i84.redis.config;\n \nimport org.springframework.beans.factory.annotation.Value;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.core.env.MapPropertySource;\nimport org.springframework.data.redis.connection.RedisClusterConfiguration;\nimport org.springframework.data.redis.connection.RedisConnectionFactory;\nimport org.springframework.data.redis.connection.RedisNode;\nimport org.springframework.data.redis.connection.jedis.JedisClientConfiguration;\nimport org.springframework.data.redis.connection.jedis.JedisClusterConnection;\nimport org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;\nimport org.springframework.data.redis.core.RedisTemplate;\nimport org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;\nimport org.springframework.data.redis.serializer.StringRedisSerializer;\n\nimport java.io.Serializable;\nimport java.util.HashMap;\nimport java.util.HashSet;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n *  \n * @version 0.1\n * @since 11/28/18\n */\n@Configuration\npublic class JedisClusterConf {\n\n    @Value(\"${spring.redis.cluster.nodes}\")\n    private String clusterNodes ;\n\n\n    @Value(\"${spring.redis.cluster.max-redirects}\")\n    private int maxRedirects ;\n\n    @Value(\"${spring.redis.cluster.timeout}\")\n    private int timeout ;\n\n    @Value(\"${spring.redis.jedis.pool.max-active}\")\n    private int maxActive ;\n\n\n    @Value(\"${spring.redis.jedis.pool.max-idle}\")\n    private int maxIdle ;\n\n    @Value(\"${spring.redis.jedis.pool.min-idle}\")\n    private int minIdle ;\n \n    @Bean\n    public RedisConnectionFactory myLettuceConnectionFactory() {\n\n        Map\u0026lt;String, Object\u0026gt; source = new HashMap\u0026lt;String, Object\u0026gt;();\n        source.put(\"spring.redis.cluster.nodes\", clusterNodes);\n        source.put(\"spring.redis.cluster.timeout\", timeout);\n        source.put(\"spring.redis.cluster.max-redirects\", maxRedirects);\n\n        RedisClusterConfiguration redisClusterConfiguration;\n        redisClusterConfiguration = new RedisClusterConfiguration(new MapPropertySource(\"RedisClusterConfiguration\", source));\n        return new LettuceConnectionFactory(redisClusterConfiguration);\n    }\n\n\n    @Bean\n    public RedisTemplate\u0026lt;String, Serializable\u0026gt; redisTemplate() {\n        RedisTemplate\u0026lt;String, Serializable\u0026gt; template = new RedisTemplate\u0026lt;String, Serializable\u0026gt;();\n        template.setKeySerializer(new StringRedisSerializer());\n        template.setValueSerializer(new GenericJackson2JsonRedisSerializer());\n        template.setConnectionFactory(myLettuceConnectionFactory());\n        return template;\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-使用\" class=\"anchor\" href=\"#5-%E4%BD%BF%E7%94%A8\"\u003E\u003C/a\u003E5. 使用\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E@Autowired\nprivate RedisTemplate redisTemplate;\n\n@Test\npublic void redisTemplate() throws Exception {\n    redisTemplate.opsForValue().set(\"author\", \"fff\");\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以关掉节点测试取值是否正常\u003C/li\u003E\n\u003Cli\u003E可以多设置几个值，看能不能设值到不同节点\u003C/li\u003E\n\u003C/ul\u003E","1130005":"\u003Ch4\u003E\n\u003Ca id=\"1查看数据库是否为cdb\" class=\"anchor\" href=\"#1%E6%9F%A5%E7%9C%8B%E6%95%B0%E6%8D%AE%E5%BA%93%E6%98%AF%E5%90%A6%E4%B8%BAcdb\"\u003E\u003C/a\u003E1.查看数据库是否为CDB\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eselect name, decode(cdb, 'YES', 'Multitenant Option enabled', 'Regular 12c Database: ') \"Multitenant Option\" , open_mode, con_id from v$database;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003EYES表示该数据库是CDB,如果是NO表示是NO-CDB(普通数据库)\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2查看当前容器container\" class=\"anchor\" href=\"#2%E6%9F%A5%E7%9C%8B%E5%BD%93%E5%89%8D%E5%AE%B9%E5%99%A8container\"\u003E\u003C/a\u003E2.查看当前容器（Container）\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eselect sys_context('userenv', 'con_name') \"Container DB\" from dual;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3查看cdb容器中的pdbs信息\" class=\"anchor\" href=\"#3%E6%9F%A5%E7%9C%8Bcdb%E5%AE%B9%E5%99%A8%E4%B8%AD%E7%9A%84pdbs%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E3.查看CDB容器中的PDBS信息\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Eselect con_id, dbid, guid, name , open_mode from v$pdbs;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4启动pdb数据库要用sysdba启动-sys\" class=\"anchor\" href=\"#4%E5%90%AF%E5%8A%A8pdb%E6%95%B0%E6%8D%AE%E5%BA%93%E8%A6%81%E7%94%A8sysdba%E5%90%AF%E5%8A%A8-sys\"\u003E\u003C/a\u003E4.启动PDB数据库（要用sysdba启动-sys）\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Ealter pluggable database PDBEPPS open;\n\nalter PLUGGABLE DATABASE PDBGZFBC SAVE STATE;--保存开启状态\n\nalter pluggable database PDBEPPS close;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"5在容器间切换\" class=\"anchor\" href=\"#5%E5%9C%A8%E5%AE%B9%E5%99%A8%E9%97%B4%E5%88%87%E6%8D%A2\"\u003E\u003C/a\u003E5.在容器间切换\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Ealter session set container=PDBEPPS;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"6删除pdb\" class=\"anchor\" href=\"#6%E5%88%A0%E9%99%A4pdb\"\u003E\u003C/a\u003E6.删除pdb\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003E--与删除表空间类似，可以级联删除数据文件\ndrop pluggable database pdb2;\ndrop pluggable database pdb2 including datafiles;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"7unplug\" class=\"anchor\" href=\"#7unplug\"\u003E\u003C/a\u003E7.unplug\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003E--unplug后pdb只能mount不能open\nalter pluggable database pdb2 unplug into '/tmp/pdb2.xml';\n\n--unplug后删除pdb，再使用xml文件加回pdb\ndrop pluggable database pdb2;\ncreate pluggable database pdb2 using '/tmp/pdb2.xml' nocopy; \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cpre\u003E\u003Ccode\u003ESQL\u0026gt; select name, cdb, open_mode, con_id from v$database;\nSQL\u0026gt; select sys_context('userenv', 'con_name') \"Container DB\" from dual;\nSQL\u0026gt; select con_id, dbid, guid, name, open_mode from v$pdbs;\nSQL\u0026gt; SELECT * FROM v$instance;\nSQL\u0026gt; SELECT * FROM v$database;\nSQL\u0026gt; SELECT * FROM dba_data_files;\nSQL\u0026gt; SELECT * FROM dba_temp_files;\nSQL\u0026gt; SELECT * FROM dba_tablespaces;\nSQL\u0026gt; SELECT * FROM v$parameter;\nSQL\u0026gt; SELECT * FROM v$parameter2;\nSQL\u0026gt; SELECT * FROM v$controlfile;\nSQL\u0026gt; SELECT * FROM v$log;\nSQL\u0026gt; SELECT * FROM v$logfile ORDER BY group# ASC;\nSQL\u0026gt; SELECT THREAD#,SEQUENCE#,NAME,ROUND(BLOCKS * BLOCK_SIZE / 1024 / 1024) AS \"SIZE(M)\",COMPLETION_TIME,DELETED,ARCHIVED FROM V$ARCHIVED_LOG;\nSQL\u0026gt; SELECT * FROM DBA_USERS WHERE ACCOUNT_STATUS = 'OPEN';\nSQL\u0026gt; SELECT username, ACCOUNT_STATUS, CREATED, CON_ID FROM CDB_USERS WHERE account_status='OPEN' ORDER BY CON_ID ASC;\nSQL\u0026gt; SELECT GRANTEE, PRIVILEGE, CON_ID FROM CDB_SYS_PRIVS WHERE GRANTEE = 'PDB_DBA';\nSQL\u0026gt; SELECT * FROM CDB_SYS_PRIVS WHERE GRANTEE = 'PDB_ADMIN';\nSQL\u0026gt; SELECT INSTANCE_NAME,STATUS,INSTANCE_ROLE FROM V$INSTANCE;\nSQL\u0026gt; SELECT * FROM v$asm_disk;\nSQL\u0026gt; SELECT * FROM v$asm_diskgroup;\nSQL\u0026gt; alter session set container=ORCLPDB;\nSQL\u0026gt; alter session set container=CDB$ROOT;\nSQL\u0026gt; show con_name;\n\n\u003C/code\u003E\u003C/pre\u003E","679743":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo脏读\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E8%84%8F%E8%AF%BB\"\u003E\u003C/a\u003E1. 示例demo（脏读）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 业务整体需要使用完整的synchronized，保持业务的原子性。\n * @author alienware\n *\n */\npublic class DirtyRead {\n\n\tprivate String username = \"bjsxt\";\n\tprivate String password = \"123\";\n\t\n\tpublic synchronized void setValue(String username, String password){\n\t\tthis.username = username;\n\t\t\n\t\ttry {\n\t\t\tThread.sleep(2000);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\t\n\t\tthis.password = password;\n\t\t\n\t\tSystem.out.println(\"setValue最终结果：username = \" + username + \" , password = \" + password);\n\t}\n\t\n\tpublic void getValue(){\n\t\tSystem.out.println(\"getValue方法得到：username = \" + this.username + \" , password = \" + this.password);\n\t}\n\t\n\t\n\tpublic static void main(String[] args) throws Exception{\n\t\t\n\t\tfinal DirtyRead dr = new DirtyRead();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tdr.setValue(\"z3\", \"456\");\t\t\n\t\t\t}\n\t\t});\n\t\tt1.start();\n\t\tThread.sleep(1000);\n\t\t\n\t\tdr.getValue();\n\t}\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"getValue\"方法不加synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/145839_2f05db74_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E当\"getValue\"方法加上synchronized 时，执行结果：\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0822/145914_cad59324_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-案例说明\" class=\"anchor\" href=\"#2-%E6%A1%88%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 案例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，dr对象可以以异步的方式调用对象中的非synchronized修饰的方法\u003C/li\u003E\n\u003Cli\u003Et1线程先持有object对象的Lock锁，dr对象如果在这个时候调用对象中的同步（synchronized）方法则需等待，也就是同步\u003C/li\u003E\n\u003C/ul\u003E","735206":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建可重用且固定线程数的线程池\u003C/li\u003E\n\u003Cli\u003E如果线程池中的所有线程都处于活动状态，此时再提交任务就在队列中等待，直到有可用线程；\u003C/li\u003E\n\u003Cli\u003E如果线程池中的某个线程由于异常而结束时，线程池就会再补充一条新线程。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic static ExecutorService newFixedThreadPool(int nThreads) {\n    return new ThreadPoolExecutor(nThreads, nThreads,\n                                  0L, TimeUnit.MILLISECONDS,\n                                  //使用一个基于FIFO排序的阻塞队列，在所有corePoolSize线程都忙时新任务将在队列中等待\n                                  new LinkedBlockingQueue\u0026lt;Runnable\u0026gt;());\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E使用的是LinkedBlockingQueue无界队列，主要问题是堆积的请求处理队列可能会耗费非常大的内存，甚至OOM\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n\n/**\n * 测试testFixedThreadPool\n */\npublic static void testFixedThreadPool() {\n    ExecutorService executorService = Executors.newFixedThreadPool(2);\n\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.execute(new TempTask(i));\n    }\n\n    executorService.shutdown();\n\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/111352_a2851650_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","748710":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.height.concurrent019.fxz;\n\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Random;\nimport java.util.concurrent.Semaphore;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/11\n */\npublic class TestSemaphore {\n\n\n    public static void main(String[] args) {\n\n        final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n        // 只运行5个线程同时进行\n        Semaphore semaphore = new Semaphore(5);\n\n        for (int i = 0; i \u0026lt; 20; i++) {\n            final int INDEX = i;\n\n            new Thread(() -\u0026gt; {\n                try {\n                    // 获取许可\n                    semaphore.acquire();\n                    Thread.sleep(1000);\n                    System.out.println(format.format(new Date()) + \" 线程\" + INDEX + \"开始\");\n                    // 访问结束，释放\n                    semaphore.release();\n                } catch (InterruptedException e) {\n                    e.printStackTrace();\n                }\n            }).start();\n        }\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0925/120014_3504792a_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E可以实现限流\u003C/li\u003E\n\u003C/ul\u003E","822721":"\u003Ch3\u003E\n\u003Ca id=\"1-构造说明\" class=\"anchor\" href=\"#1-%E6%9E%84%E9%80%A0%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 构造说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eringbuffer\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建单生产者的ringbuffer\n * @param factory         : 事件工厂\n * @param bufferSize      : 缓冲大小\n * @param waitStrategy    : 等待策略\n */\nRingBuffer\u0026lt;OrderEvent\u0026gt; ringBuffer = RingBuffer.createSingleProducer(new EventFactory\u0026lt;OrderEvent\u0026gt;() {\n    @Override\n    public OrderEvent newInstance() {\n        return new OrderEvent();\n    }\n}, BUFFER_SIZE, new YieldingWaitStrategy());\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EBatchEventProcessor\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建消息处理器\n * @param dataProvider         : 事件工厂\n * @param sequenceBarrier      : 缓冲大小\n * @param eventHandler         : 等待策略\n */\nBatchEventProcessor\u0026lt;OrderEvent\u0026gt; processor = new BatchEventProcessor\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new EventHandler\u0026lt;OrderEvent\u0026gt;() {\n    @Override\n    public void onEvent(OrderEvent orderEvent, long l, boolean b) throws Exception {\n        System.out.println(orderEvent);\n    }\n});\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EWorkerPool\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * 创建工作池\n * @param   ringBuffer          缓存\n * @param   sequenceBarrier     障碍\n * @param   exceptionHandler    异常处理\n * @param   workHandlers....    事件消费\n */\nWorkerPool\u0026lt;OrderEvent\u0026gt; workerPool = new WorkerPool\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), new WorkHandler\u0026lt;OrderEvent\u0026gt;() {\n    @Override\n    public void onEvent(OrderEvent orderEvent) throws Exception {\n        System.out.println(orderEvent);\n    }\n});\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例demo\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E2. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport com.lmax.disruptor.*;\n\nimport java.util.Random;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/28\n */\npublic class RingMain {\n\n    // 缓冲大小\n    final static int BUFFER_SIZE = 1024;\n\n    // 线程大小\n    final static int THREAD_NUMBERS = 4;\n\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n\n        /**\n         * 创建单生产者的ringbuffer\n         * @param factory         : 事件工厂\n         * @param bufferSize      : 缓冲大小\n         * @param waitStrategy    : 等待策略\n         */\n        RingBuffer\u0026lt;OrderEvent\u0026gt; ringBuffer = RingBuffer.createSingleProducer(new EventFactory\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public OrderEvent newInstance() {\n                return new OrderEvent();\n            }\n        }, BUFFER_SIZE, new YieldingWaitStrategy());\n\n\n        //创建SequenceBarrier\n        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();\n\n        /**\n         * 创建消息处理器\n         * @param dataProvider         : 事件工厂\n         * @param sequenceBarrier      : 缓冲大小\n         * @param eventHandler         : 等待策略\n         */\n        BatchEventProcessor\u0026lt;OrderEvent\u0026gt; processor = new BatchEventProcessor\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new EventHandler\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public void onEvent(OrderEvent orderEvent, long l, boolean b) throws Exception {\n                System.out.println(orderEvent);\n            }\n        });\n\n\n        //这一步的目的就是把消费者的位置信息引用注入到生产者    如果只有一个消费者的情况可以省略\n        ringBuffer.addGatingSequences(processor.getSequence());\n\n\n        // 创建线程池\n        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUMBERS);\n        //把消息处理器提交到线程池\n        executorService.submit(processor);\n\n        // 生产数据\n        Future\u0026lt;Void\u0026gt; future = executorService.submit(new Callable\u0026lt;Void\u0026gt;() {\n            @Override\n            public Void call() throws Exception {\n                long seq = 0 ;\n                for (int i = 0 ; i \u0026lt; 10 ; i++) {\n                    seq = ringBuffer.next() ;\n                    ringBuffer.get(seq).setName(\"name_\" + i);\n                    ringBuffer.get(seq).setPrice(new Random().nextInt(100));\n                    ringBuffer.publish(seq);\n                }\n                return null;\n            }\n        });\n\n        //等待生产者结束\n        future.get();\n\n        //等上1秒，等消费都处理完成\n        Thread.sleep(1000);\n\n        //通知事件(或者说消息)处理器 可以结束了（并不是马上结束!!!）\n        processor.halt();\n\n        //终止线程\n        executorService.shutdown();\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport com.lmax.disruptor.*;\n\nimport java.util.Random;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/28\n */\npublic class RingMain2 {\n\n    // 缓冲大小\n    final static int BUFFER_SIZE = 1024;\n\n    // 线程大小\n    final static int THREAD_NUMBERS = 4;\n\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n        RingBuffer\u0026lt;OrderEvent\u0026gt; ringBuffer = RingBuffer.createSingleProducer(new EventFactory\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public OrderEvent newInstance() {\n                return new OrderEvent();\n            }\n        }, BUFFER_SIZE, new YieldingWaitStrategy());\n\n        SequenceBarrier sequenceBarrier = ringBuffer.newBarrier();\n\n        // 线程池\n        ExecutorService executor = Executors.newFixedThreadPool(THREAD_NUMBERS);\n\n        /**\n         * 创建工作池\n         * @param   ringBuffer          缓存\n         * @param   sequenceBarrier     障碍\n         * @param   exceptionHandler    异常处理\n         * @param   workHandlers....    事件消费\n         */\n        WorkerPool\u0026lt;OrderEvent\u0026gt; workerPool = new WorkerPool\u0026lt;\u0026gt;(ringBuffer, sequenceBarrier, new IgnoreExceptionHandler(), new WorkHandler\u0026lt;OrderEvent\u0026gt;() {\n            @Override\n            public void onEvent(OrderEvent orderEvent) throws Exception {\n                System.out.println(orderEvent);\n            }\n        });\n\n        workerPool.start(executor);\n\n        //下面这个生产8个数据\n        long seq = -1;\n        for (int i = 0; i \u0026lt; 8; i++) {\n            seq = ringBuffer.next();\n            ringBuffer.get(seq).setName(\"name_\" + i);\n            ringBuffer.get(seq).setPrice(new Random().nextInt(100));\n            ringBuffer.publish(seq);\n        }\n\n        Thread.sleep(1000);\n        workerPool.halt();\n        executor.shutdown();\n\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E","987024":"\u003Ch3\u003E\n\u003Ca id=\"1-参考链接\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5\"\u003E\u003C/a\u003E1. 参考链接\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"blogs.com/dongml/p/8719421.html\"\u003Ecentos7 python3安装\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-安装准备\" class=\"anchor\" href=\"#2-%E5%AE%89%E8%A3%85%E5%87%86%E5%A4%87\"\u003E\u003C/a\u003E2. 安装准备\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Ecentos7原本就安装了Python2，而且这个Python2不能被删除\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1030/160808_f8558c4c_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装相关软件包\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esudo yum update -y  # 更新系统软件包\nsudo yum groupinstall -y \"development tools\" \nsudo yum install zlib zlib-devel bzip2-devel openssl openssl-devel libffi-devel ncurses-devel xz-devel python3-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel expat-devel\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E下载最新版本python\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E(1) \u003Ca href=\"https://www.python.org/ftp/python/3.7.1/Python-3.7.1.tgz\"\u003Epython3.7.1 下载\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E(2) \u003Ca href=\"https://www.python.org/downloads/\"\u003Epython官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-安装python\" class=\"anchor\" href=\"#3-%E5%AE%89%E8%A3%85python\"\u003E\u003C/a\u003E3. 安装python\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E相关命令:\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 解压\n[root@localhost bin]# tar -xvf Python-3.7.1.tgz\n[root@localhost bin]# cd Python-3.7.1/\n\n# 配置安装目录\n[root@localhost bin]# ./configure --prefix=/usr/local/deve/soft/python3\n\n# 编译安装\n[root@localhost bin]# make \u0026amp;\u0026amp; make install\n\n# 设置软链\n[root@localhost bin]# ln -s /usr/local/deve/soft/python3/bin/python3 /usr/bin/python3\n[root@localhost bin]# ln -s /usr/local/deve/soft/python3/bin/pip3 /usr/bin/pip3\n\n# 安装virtualenv\n[root@localhost bin]# ./pip3 install virtualenv\n[root@localhost bin]# ln -s /usr/local/deve/soft/python3/bin/virtualenv /usr/bin/venv3\n\n# 验证是否成功\n[root@localhost bin]# python3\n[root@localhost bin]# pip3 -V\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1030/165113_a09113cc_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003E输入pip3 -V查看pip版本,安装成功则正确显示版本\u003C/p\u003E","987035":"\u003Ch3\u003E\n\u003Ca id=\"1-切换到root用户\" class=\"anchor\" href=\"#1-%E5%88%87%E6%8D%A2%E5%88%B0root%E7%94%A8%E6%88%B7\"\u003E\u003C/a\u003E1. 切换到root用户\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esu root\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-编辑网卡信息\" class=\"anchor\" href=\"#2-%E7%BC%96%E8%BE%91%E7%BD%91%E5%8D%A1%E4%BF%A1%E6%81%AF\"\u003E\u003C/a\u003E2. 编辑网卡信息\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/sysconfig/network-scripts/ifcfg-eth0\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-设置为动态获取\" class=\"anchor\" href=\"#3-%E8%AE%BE%E7%BD%AE%E4%B8%BA%E5%8A%A8%E6%80%81%E8%8E%B7%E5%8F%96\"\u003E\u003C/a\u003E3. 设置为动态获取\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EDEVICE=\"eth0\"\nBOOTPROTO=\"dhcp\"\nHWADDR=\"00:0C:29:86:A6:11\"\nIPV6INIT=\"yes\"\nNM_CONTROLLED=\"yes\"\nONBOOT=\"yes\"\nTYPE=\"Ethernet\"\nUUID=\"948534ec-43f8-4da1-8ba7-d6ff0df8fb55\"\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-设置为静态ip\" class=\"anchor\" href=\"#4-%E8%AE%BE%E7%BD%AE%E4%B8%BA%E9%9D%99%E6%80%81ip\"\u003E\u003C/a\u003E4. 设置为静态ip\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EDEVICE=\"eth0\"\nBOOTPROTO=\"static\"\nHWADDR=\"00:0C:29:86:A6:11\"\nIPV6INIT=\"yes\"\nNM_CONTROLLED=\"yes\"\nONBOOT=\"yes\"\nTYPE=\"Ethernet\"\nUUID=\"948534ec-43f8-4da1-8ba7-d6ff0df8fb55\"\nIPADDR=192.168.222.100\nNEWMASK=255.255.255.0\nGATEWAY=192.168.222.2\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-配置dns-vim-etcresolvconf\" class=\"anchor\" href=\"#5-%E9%85%8D%E7%BD%AEdns-vim-etcresolvconf\"\u003E\u003C/a\u003E5. 配置DNS vim /etc/resolv.conf\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Enameserver 192.168.222.2\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-重启网络\" class=\"anchor\" href=\"#6-%E9%87%8D%E5%90%AF%E7%BD%91%E7%BB%9C\"\u003E\u003C/a\u003E6. 重启网络\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eservice network restart\n\u003C/code\u003E\u003C/pre\u003E","1224890":"\u003Ch3\u003E\n\u003Ca id=\"1参考资料\" class=\"anchor\" href=\"#1%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1.参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"http://likaixuan.top/excelUtil#\"\u003EExcelutil\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-引入pom\" class=\"anchor\" href=\"#2-%E5%BC%95%E5%85%A5pom\"\u003E\u003C/a\u003E2. 引入pom\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;dependency\u0026gt;\n    \u0026lt;groupId\u0026gt;net.oschina.likaixuan\u0026lt;/groupId\u0026gt;\n    \u0026lt;artifactId\u0026gt;excelutil\u0026lt;/artifactId\u0026gt;\n    \u0026lt;version\u0026gt;2.0.2\u0026lt;/version\u0026gt;\n\u0026lt;/dependency\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-读取excel\" class=\"anchor\" href=\"#3-%E8%AF%BB%E5%8F%96excel\"\u003E\u003C/a\u003E3. 读取Excel\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EString keyValue =\"手机名称:phoneName,颜色:color,售价:price\"; \nList\u0026lt;PhoneModel\u0026gt; list=ExcelUtil.readXls(\"C://test.xlsx\",ExcelUtil.getMap(keyValue),\"com.lkx.model.PhoneModel\");\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-写入excel\" class=\"anchor\" href=\"#3-%E5%86%99%E5%85%A5excel\"\u003E\u003C/a\u003E3. 写入Excel\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003EString keyValue =\"手机名称:phoneName,颜色:color,售价:price\"; \nExcelUtil.exportExcel(\"d:/testsss.xls\",keyValue,list,\"com.lkx.model.PhoneModel\");\n\u003C/code\u003E\u003C/pre\u003E","1005014":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E  \u003Ca href=\"https://blog.csdn.net/see__you__again/article/details/51998038\"\u003EJVM参数设置、分析\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-常见参数配置\" class=\"anchor\" href=\"#2-%E5%B8%B8%E8%A7%81%E5%8F%82%E6%95%B0%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E2. 常见参数配置\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E参数\u003C/th\u003E\n\u003Cth\u003E说明\u003C/th\u003E\n\u003Cth\u003E默认配置\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xms\u003C/td\u003E\n\u003Ctd\u003E初始堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmx\u003C/td\u003E\n\u003Ctd\u003E最大堆大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xmn\u003C/td\u003E\n\u003Ctd\u003E配置新生代大小，对系统性能及GC有比较大影响，一般配置在堆大小的1/4到1/3左右\u003C/td\u003E\n\u003Ctd\u003E1/3\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:PermSize\u003C/td\u003E\n\u003Ctd\u003E方法区大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:MaxPermSize\u003C/td\u003E\n\u003Ctd\u003E方法区最大大小\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:NewRatio\u003C/td\u003E\n\u003Ctd\u003E老年代/新生代\u003C/td\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:SurvivorRatio\u003C/td\u003E\n\u003Ctd\u003EEden区/Form区的比例=EDEN/FROM=EDEN/TO\u003C/td\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-Xss\u003C/td\u003E\n\u003Ctd\u003E指定线程最大栈空间\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintCommandLineFlags\u003C/td\u003E\n\u003Ctd\u003E输出参数信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGC\u003C/td\u003E\n\u003Ctd\u003E打印GC日志\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E-XX:+PrintGCDetails\u003C/td\u003E\n\u003Ctd\u003E打印GC日志详细信息\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","995337":"\u003Ch3\u003E\n\u003Ca id=\"redis-列表list\" class=\"anchor\" href=\"#redis-%E5%88%97%E8%A1%A8list\"\u003E\u003C/a\u003ERedis 列表(List)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003ERedis列表是简单的字符串列表，按照插入顺序排序。你可以添加一个元素到列表的头部（左边）或者尾部（右边）\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E一个列表最多可以包含 2^32 - 1 个元素 (4294967295, 每个列表超过40亿个元素)。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Eblpop key1 [key2 ] timeout\u003C/td\u003E\n\u003Ctd\u003E移出并获取列表的第一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ebrpop key1 [key2 ] timeout\u003C/td\u003E\n\u003Ctd\u003E移出并获取列表的最后一个元素， 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Ebrpoplpush source destination timeout\u003C/td\u003E\n\u003Ctd\u003E从列表中弹出一个值，将弹出的元素插入到另外一个列表中并返回它； 如果列表没有元素会阻塞列表直到等待超时或发现可弹出元素为止。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Elindex key index\u003C/td\u003E\n\u003Ctd\u003E通过索引获取列表中的元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Elinsert key before\u003C/td\u003E\n\u003Ctd\u003Eafter pivot value  在列表的元素前或者后插入元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ellen key\u003C/td\u003E\n\u003Ctd\u003E获取列表长度\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Elpop key\u003C/td\u003E\n\u003Ctd\u003E移出并获取列表的第一个元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Elpush key value1 [value2]\u003C/td\u003E\n\u003Ctd\u003E将一个或多个值插入到列表头部\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Elpushx key value\u003C/td\u003E\n\u003Ctd\u003E将一个值插入到已存在的列表头部\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Elrange key start stop\u003C/td\u003E\n\u003Ctd\u003E获取列表指定范围内的元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Elrem key count value\u003C/td\u003E\n\u003Ctd\u003E移除列表元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Elset key index value\u003C/td\u003E\n\u003Ctd\u003E通过索引设置列表元素的值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Eltrim key start stop\u003C/td\u003E\n\u003Ctd\u003E对一个列表进行修剪(trim)，就是说，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Erpop key\u003C/td\u003E\n\u003Ctd\u003E移除列表的最后一个元素，返回值为移除的元素。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Erpoplpush source destination\u003C/td\u003E\n\u003Ctd\u003E移除列表的最后一个元素，并将该元素添加到另一个列表并返回\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Erpush key value1 [value2]\u003C/td\u003E\n\u003Ctd\u003E在列表中添加一个或多个值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E17\u003C/td\u003E\n\u003Ctd\u003Erpushx key value\u003C/td\u003E\n\u003Ctd\u003E为已存在的列表添加值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","1057853":"\u003Ch3\u003E\n\u003Ca id=\"参考资料\" class=\"anchor\" href=\"#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/Howinfun/article/details/81938161\"\u003ERedis集群添加和删除节点（主和从）\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-添加主节点\" class=\"anchor\" href=\"#1-%E6%B7%BB%E5%8A%A0%E4%B8%BB%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E1. 添加主节点\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-cluster]# /usr/local/deve/soft/redis-4.0.11/src/redis-server 7007/redis.conf  \n[root@localhost src]# ./redis-trib.rb add-node 192.168.222.129:7007 192.168.222.129:7001\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E刚加入的节点是无solt（槽）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-为主节点分配槽\" class=\"anchor\" href=\"#2-%E4%B8%BA%E4%B8%BB%E8%8A%82%E7%82%B9%E5%88%86%E9%85%8D%E6%A7%BD\"\u003E\u003C/a\u003E2. 为主节点分配槽\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost src]# ./redis-trib.rb reshard 192.168.222.129:7007\n\nHow many slots do you want to move (from 1 to 16384)?  输入要分配的槽数量\nWhat is the receiving node ID? 输入新节点的ID\nPlease enter all the source node IDs.\nType 'all' to use all the nodes as source nodes for the hash slots.\nType 'done' once you entered all the source nodes IDs.\nSource node #1:all\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-添加从节点\" class=\"anchor\" href=\"#3-%E6%B7%BB%E5%8A%A0%E4%BB%8E%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E3. 添加从节点\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E新增节点\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-cluster]# /usr/local/deve/soft/redis-4.0.11/src/redis-server 7008/redis.conf \n[root@localhost src]# ./redis-trib.rb add-node 192.168.222.129:7008 192.168.222.129:7001\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E指定主节点\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 登录7008节点\n[root@localhost src]# ./redis-cli -c -h 192.168.222.129 -p 7008\n192.168.222.129:7008\u0026gt; cluster replicate 0e2ba9c12d9c211d07530fc9242c187d175ceedb\nOK\n192.168.222.129:7008\u0026gt; cluster nodes\n24ef75ce1385a29c11e1e970143670630a345711 192.168.222.129:7002@17002 master - 0 1543310055598 2 connected 5461-10922\nbfa68ee0d6335ebd93c8bc58f73dd67c6e67c353 192.168.222.129:7001@17001 master - 0 1543310056000 1 connected 0-5460\n5b98ed16b3ead28b072762650450b9441296ab18 192.168.222.129:7006@17006 slave bfa68ee0d6335ebd93c8bc58f73dd67c6e67c353 0 1543310055000 1 connected\n3875de68fe213d19fb8e64311031b0ebdd63e566 192.168.222.129:7004@17004 slave 24ef75ce1385a29c11e1e970143670630a345711 0 1543310055000 2 connected\n1e61f26a3f8057264c956c4d02f6f57abf4d2d67 192.168.222.129:7003@17003 master - 0 1543310055000 3 connected 11923-16383\n287476ede647ca6eca1f2da01f1bb5efb49af4a2 192.168.222.129:7008@17008 myself,slave 0e2ba9c12d9c211d07530fc9242c187d175ceedb 0 1543310056000 0 connected\n267be6e526fde26d544a5e041db560323f037bad 192.168.222.129:7005@17005 slave 1e61f26a3f8057264c956c4d02f6f57abf4d2d67 0 1543310056000 3 connected\n0e2ba9c12d9c211d07530fc9242c187d175ceedb 192.168.222.129:7007@17007 master - 0 1543310056802 7 connected 10923-11922\n192.168.222.129:7008\u0026gt; \n\n\u003C/code\u003E\u003C/pre\u003E","1067923":"\u003Ch3\u003E\n\u003Ca id=\"1warning-overcommit_memory-is-set-to-0-background-save-may-fail-under-low-memory-condition-to-fix-this-issue-add-vmovercommit_memory--1-to-etcsysctlconf-and-then-reboot-or-run-the-command-sysctl-vmovercommit_memory1-for-this-to-take-effect\" class=\"anchor\" href=\"#1warning-overcommit_memory-is-set-to-0-background-save-may-fail-under-low-memory-condition-to-fix-this-issue-add-vmovercommit_memory--1-to-etcsysctlconf-and-then-reboot-or-run-the-command-sysctl-vmovercommit_memory1-for-this-to-take-effect\"\u003E\u003C/a\u003E1.WARNING overcommit_memory is set to 0! Background save may fail under low memory condition. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E echo 1 \u0026gt; /proc/sys/vm/overcommit_memory  不需要启机器就生效\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2warning-the-tcp-backlog-setting-of-511-cannot-be-enforced-because-procsysnetcoresomaxconn-is-set-to-the-lower-value-of-128\" class=\"anchor\" href=\"#2warning-the-tcp-backlog-setting-of-511-cannot-be-enforced-because-procsysnetcoresomaxconn-is-set-to-the-lower-value-of-128\"\u003E\u003C/a\u003E2.WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E echo 511 \u0026gt; /proc/sys/net/core/somaxconn\n\u003C/code\u003E\u003C/pre\u003E","1130007":"\u003Ch4\u003E\n\u003Ca id=\"1-ora-65024\" class=\"anchor\" href=\"#1-ora-65024\"\u003E\u003C/a\u003E1. ora-65024\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201806/06160106_0knG.png\" alt=\"ora-65024 数据库未打开\" title=\"在这里输入图片标题\"\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E启动PDB数据库（要用sysdba启动-sys）\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Ealter pluggable database PDBEPPS open;\n\nalter PLUGGABLE DATABASE PDBGZFBC SAVE STATE;--保存开启状态\n\nalter pluggable database PDBEPPS close;\n\u003C/code\u003E\u003C/pre\u003E","680333":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo多个同步方法串联调用\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E5%A4%9A%E4%B8%AA%E5%90%8C%E6%AD%A5%E6%96%B9%E6%B3%95%E4%B8%B2%E8%81%94%E8%B0%83%E7%94%A8\"\u003E\u003C/a\u003E1. 示例demo（多个同步方法串联调用）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/**\n * synchronized的重入\n * @author alienware\n *\n */\npublic class SyncDubbo1 {\n\n\tpublic synchronized void method1(){\n\t\tSystem.out.println(\"method1..\");\n\t\tmethod2();\n\t}\n\tpublic synchronized void method2(){\n\t\tSystem.out.println(\"method2..\");\n\t\tmethod3();\n\t}\n\tpublic synchronized void method3(){\n\t\tSystem.out.println(\"method3..\");\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal SyncDubbo1 sd = new SyncDubbo1();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tsd.method1();\n\t\t\t}\n\t\t});\n\t\tt1.start();\n\t}\n}\n\n\u003C/code\u003E\u003C/pre\u003E","735270":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建一个单线程的Executor，如果该线程因为异常而结束就新建一条线程来继续执行后续的任务\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic static ExecutorService newSingleThreadExecutor() {\n   return new FinalizableDelegatedExecutorService\n                     //corePoolSize和maximumPoolSize都等于，表示固定线程池大小为1\n                        (new ThreadPoolExecutor(1, 1,\n                                                0L, TimeUnit.MILLISECONDS,\n                                                new LinkedBlockingQueue\u0026lt;Runnable\u0026gt;()));\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E使用的是LinkedBlockingQueue无界队列，主要问题是堆积的请求处理队列可能会耗费非常大的内存，甚至OOM\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n/**\n * 测试SingleThreadPool\n */\npublic static void testSingleThreadPool() {\n    ExecutorService executorService = Executors.newSingleThreadExecutor();\n\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.execute(new TempTask(i));\n    }\n\n    executorService.shutdown();\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/111214_4d11eca3_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","798219":"\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0925/173137_9be6f511_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","822750":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0930/151758_9fe89070_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.YieldingWaitStrategy;\nimport com.lmax.disruptor.dsl.Disruptor;\nimport com.lmax.disruptor.dsl.ProducerType;\n\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class LineMain {\n\n    private final static int BUFFER_SIZE = 1024;\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n\n        long beginTime = System.currentTimeMillis();\n\n        ExecutorService executorService = Executors.newFixedThreadPool(4);\n\n        // 1. 创建disruptor\n        Disruptor\u0026lt;OrderEvent\u0026gt; disruptor = new Disruptor\u0026lt;OrderEvent\u0026gt;(\n                () -\u0026gt; {\n                    return new OrderEvent();\n                },\n                BUFFER_SIZE,\n                executorService,\n                ProducerType.SINGLE,\n                new YieldingWaitStrategy()\n        );\n\n        // 2. 设置消费顺序（直线顺序消费）\n        disruptor.handleEventsWith(new OrderHandler1())\n                .handleEventsWith(new OrderHandler2())\n                .handleEventsWith(new OrderHandler3());\n\n        // 3. 启动\n        disruptor.start();\n\n        // 4. 生产数据\n        Future\u0026lt;?\u0026gt; future = executorService.submit(() -\u0026gt; {\n            for (int i = 0; i \u0026lt; 5; i++) {\n                disruptor.publishEvent((OrderEvent event, long sequence) -\u0026gt; {\n                    event.setName(\"初始化订单\");\n                    System.out.println(\"初始化订单\");\n                });\n            }\n            return null;\n        });\n\n        // 5. 保证数据生成完成\n        future.get();\n\n        // 6. 关闭资源\n        disruptor.shutdown();\n        executorService.shutdown();\n\n        System.out.println(\"耗时：\" + (System.currentTimeMillis() - beginTime));\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EOrderHandler1\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.EventHandler;\nimport com.lmax.disruptor.WorkHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class OrderHandler1 implements EventHandler\u0026lt;OrderEvent\u0026gt;, WorkHandler\u0026lt;OrderEvent\u0026gt; {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {\n        onEvent(event);\n    }\n\n    @Override\n    public void onEvent(OrderEvent event) throws Exception {\n        event.setName(FORMAT.format(new Date()) + \" 订单 \");\n        System.out.println(FORMAT.format(new Date()) + \" ___   OrderHandler1 处理订单设置订单名 \");\n        Thread.sleep(1000);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EOrderHandler2\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E\nimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.EventHandler;\nimport com.lmax.disruptor.WorkHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class OrderHandler2 implements EventHandler\u0026lt;OrderEvent\u0026gt;, WorkHandler\u0026lt;OrderEvent\u0026gt; {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {\n        onEvent(event);\n    }\n\n    @Override\n    public void onEvent(OrderEvent event) throws Exception {\n        event.setPrice(100);\n        System.out.println(FORMAT.format(new Date()) + \" ___   OrderHandler2 处理订单设置订单价格 \");\n        Thread.sleep(500);\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EOrderHandler3\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.EventHandler;\nimport com.lmax.disruptor.WorkHandler;\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.Random;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class OrderHandler3 implements EventHandler\u0026lt;OrderEvent\u0026gt;, WorkHandler\u0026lt;OrderEvent\u0026gt; {\n\n    private static final SimpleDateFormat FORMAT = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    @Override\n    public void onEvent(OrderEvent event, long sequence, boolean endOfBatch) throws Exception {\n        onEvent(event);\n    }\n\n    @Override\n    public void onEvent(OrderEvent event) throws Exception {\n        event.setPrice(100 - new Random().nextInt(1));\n        System.out.println(FORMAT.format(new Date()) + \" ___   OrderHandler3 处理订单随机减 \");\n        Thread.sleep(500);\n    }\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E模拟“消费1” -- “消费2” -- “消费3”\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0930/151143_1ac857f0_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","987025":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/yaoqiwaimai/article/details/74626851\"\u003Ecentos 7下安装pycharm专业版\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.jetbrains.com/pycharm/download/#section=linux\"\u003Epycharm下载地址\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.cnblogs.com/lenmom/p/9193183.html\"\u003ECentOS 7 创建桌面快捷方式\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-在桌面添加快捷方式\" class=\"anchor\" href=\"#2-%E5%9C%A8%E6%A1%8C%E9%9D%A2%E6%B7%BB%E5%8A%A0%E5%BF%AB%E6%8D%B7%E6%96%B9%E5%BC%8F\"\u003E\u003C/a\u003E2. 在桌面添加快捷方式\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在/usr/share/applications目录下创建以.desktop为后缀的文件\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 非root用户\nvi /home/fxz/Desktop/eclipse.desktop\n\n# root用户\nvim /usr/share/applications/pycharm.desktop\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E将以下内容写入上面创建的文件中\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E#!/usr/bin/env xdg-open\n[Desktop Entry]\nEncoding=UTF-8\nName=Pycharm\nComment=pycharm-2018.1.1\nExec=/usr/local/deve/soft/pycharm-2018.2.4/bin/pycharm.sh\nIcon=/usr/local/deve/soft/pycharm-2018.2.4/bin/pycharm.png\nTerminal=false\nStartupNotify=true\nType=Application    #快捷方式的类型\nCategories=Application;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003Eps：根据设置不同软件的快捷键，修改下内容即可\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E给文件赋予可执行权限\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Echmod a+x /usr/share/applications/pycharm.desktop\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E点击左上角的位置，找到/usr/share/applications目录下，将会看到你所配置的图标，右击复制到桌面即可。\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1031/105040_743082d0_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\n\u003C/li\u003E\n\u003C/ul\u003E","1023958":"\u003Ch3\u003E\n\u003Ca id=\"1-在命令上输入\" class=\"anchor\" href=\"#1-%E5%9C%A8%E5%91%BD%E4%BB%A4%E4%B8%8A%E8%BE%93%E5%85%A5\"\u003E\u003C/a\u003E1. 在命令上输入\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Einit 3 命令 切换到dos界面\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Einit 5 命令 切换到图形界面\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-修改方法为\" class=\"anchor\" href=\"#2-%E4%BF%AE%E6%94%B9%E6%96%B9%E6%B3%95%E4%B8%BA\"\u003E\u003C/a\u003E2. 修改方法为：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 首先删除已经存在的符号链接：\n\nrm /etc/systemd/system/default.target  \n\n# 默认级别转换为3(文本模式)： \n\nln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target \n 或者默认级别转换为5(图形模式)：\nln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target\n\n# 重启：\nreboot \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-centos7以下的版本\" class=\"anchor\" href=\"#3-centos7%E4%BB%A5%E4%B8%8B%E7%9A%84%E7%89%88%E6%9C%AC\"\u003E\u003C/a\u003E3. centos7以下的版本\u003C/h3\u003E\n\u003Cp\u003E以管理员权限编辑/etc/inittab\n把\nid:5:initdefault:\n改为\nid:3:initdefault:\n就ok。\u003C/p\u003E","995440":"\u003Ch3\u003E\n\u003Ca id=\"redis-集合set\" class=\"anchor\" href=\"#redis-%E9%9B%86%E5%90%88set\"\u003E\u003C/a\u003Eredis 集合(set)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 的 set 是 string 类型的无序集合。集合成员是唯一的，这就意味着集合中不能出现重复的数据。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 中集合是通过哈希表实现的，所以添加，删除，查找的复杂度都是 o(1)。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储40多亿个成员)\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Esadd key member1 [member2]\u003C/td\u003E\n\u003Ctd\u003E向集合添加一个或多个成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Escard key\u003C/td\u003E\n\u003Ctd\u003E获取集合的成员数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Esdiff key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的差集\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Esdiffstore destination key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的差集并存储在 destination 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Esinter key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的交集\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Esinterstore destination key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回给定所有集合的交集并存储在 destination 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Esismember key member\u003C/td\u003E\n\u003Ctd\u003E判断 member 元素是否是集合 key 的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Esmembers key\u003C/td\u003E\n\u003Ctd\u003E返回集合中的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Esmove source destination member\u003C/td\u003E\n\u003Ctd\u003E将 member 元素从 source 集合移动到 destination 集合\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Espop key\u003C/td\u003E\n\u003Ctd\u003E移除并返回集合中的一个随机元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Esrandmember key [count]\u003C/td\u003E\n\u003Ctd\u003E返回集合中一个或多个随机数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Esrem key member1 [member2]\u003C/td\u003E\n\u003Ctd\u003E移除集合中一个或多个成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Esunion key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E返回所有给定集合的并集\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Esunionstore destination key1 [key2]\u003C/td\u003E\n\u003Ctd\u003E所有给定集合的并集存储在 destination 集合中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Esscan key cursor [match pattern] [count count]\u003C/td\u003E\n\u003Ctd\u003E迭代集合中的元素\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","1058134":"\u003Ch3\u003E\n\u003Ca id=\"参考资料\" class=\"anchor\" href=\"#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/Howinfun/article/details/81938161\"\u003ERedis集群添加和删除节点（主和从）\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-删除主节点\" class=\"anchor\" href=\"#1-%E5%88%A0%E9%99%A4%E4%B8%BB%E8%8A%82%E7%82%B9\"\u003E\u003C/a\u003E1. 删除主节点\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E归还槽solt\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E这里输入代码\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1127/173516_9946fa85_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E删除从节点非常简单，删除的时候指定ip+端口以及节点id即可。\u003C/li\u003E\n\u003Cli\u003E但是删除主节点可不能直接删除，一定要先将slot槽重新移动到其他主节点那里再进行删除操作，不然存放的数据就丢失了。\u003C/li\u003E\n\u003Cli\u003E我们现在先尝试删除一个从节点（7008）\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-删除子节点用del-node命令\" class=\"anchor\" href=\"#1-%E5%88%A0%E9%99%A4%E5%AD%90%E8%8A%82%E7%82%B9%E7%94%A8del-node%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E1. 删除子节点用del-node命令。\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E此命令需要制定删除节点的ip和端口，以及节点的id\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost src]$ ./redis-trib.rb del-node 192.168.222.129:7006 5b98ed16b3ead28b072762650450b9441296ab18\n\u0026gt;\u0026gt;\u0026gt; Removing node 5b98ed16b3ead28b072762650450b9441296ab18 from cluster 192.168.222.129:7006\n\u0026gt;\u0026gt;\u0026gt; Sending CLUSTER FORGET messages to the cluster...\n\u0026gt;\u0026gt;\u0026gt; SHUTDOWN the node.\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E删除后我们再次查看集群的节点信息，如下所示，7006从节点已经被移除掉。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost redis-cluster]$ ./redis-cluster 7002\n192.168.222.129:7002\u0026gt; cluster nodes\n24ef75ce1385a29c11e1e970143670630a345711 192.168.222.129:7002@17002 myself,master - 0 1543310814000 2 connected 5461-10922\n0e2ba9c12d9c211d07530fc9242c187d175ceedb 192.168.222.129:7007@17007 master - 0 1543310815000 7 connected 10923-11922\n267be6e526fde26d544a5e041db560323f037bad 192.168.222.129:7005@17005 slave 1e61f26a3f8057264c956c4d02f6f57abf4d2d67 0 1543310814000 5 connected\n3875de68fe213d19fb8e64311031b0ebdd63e566 192.168.222.129:7004@17004 slave 24ef75ce1385a29c11e1e970143670630a345711 0 1543310815000 4 connected\nbfa68ee0d6335ebd93c8bc58f73dd67c6e67c353 192.168.222.129:7001@17001 master - 0 1543310814504 1 connected 0-5460\n287476ede647ca6eca1f2da01f1bb5efb49af4a2 192.168.222.129:7008@17008 slave 0e2ba9c12d9c211d07530fc9242c187d175ceedb 0 1543310815006 7 connected\n1e61f26a3f8057264c956c4d02f6f57abf4d2d67 192.168.222.129:7003@17003 master - 0 1543310816011 3 connected 11923-16383\n192.168.222.129:7002\u0026gt; \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E另外，我们可以发现，7008的redis服务进程也被kill掉了。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-cluster]# ps -ef | grep redis\nroot      10686      1  0 17:09 ?        00:00:01 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7008 [cluster]\nroot      16879      1  0 16:23 ?        00:00:06 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7001 [cluster]\nroot      16881      1  0 16:23 ?        00:00:05 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7002 [cluster]\nroot      16889      1  0 16:23 ?        00:00:06 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7003 [cluster]\nroot      16894      1  0 16:23 ?        00:00:05 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7004 [cluster]\nroot      16899      1  0 16:23 ?        00:00:05 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7005 [cluster] \nroot      81308      1  0 16:47 ?        00:00:04 /usr/local/deve/soft/redis-4.0.11/src/redis-server 192.168.222.129:7007 [cluster]\n\u003C/code\u003E\u003C/pre\u003E","1028825":"\u003Ch3\u003E\n\u003Ca id=\"1前言\" class=\"anchor\" href=\"#1%E5%89%8D%E8%A8%80\"\u003E\u003C/a\u003E1、前言\u003C/h3\u003E\n\u003Cp\u003ERedis是一种高级key-value数据库。它跟memcached类似，不过数据可以持久化，而且支持的数据类型很丰富。有字符串，链表，集 合和有序集合。支持在服务器端计算集合的并，交和补集(difference)等，还支持多种排序功能。所以Redis也可以被看成是一个数据结构服务 器。\nRedis的所有数据都是保存在内存中，然后不定期的通过异步方式保存到磁盘上(这称为“半持久化模式”)；也可以把每一次数据变化都写入到一个append only file(aof)里面(这称为“全持久化模式”)。\u003C/p\u003E\n\u003Cp\u003E由于Redis的数据都存放在内存中，如果没有配置持久化，redis重启后数据就全丢失了，于是需要开启redis的持久化功能，将数据保存到磁盘上，当redis重启后，可以从磁盘中恢复数据。redis提供两种方式进行持久化，一种是RDB持久化（原理是将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化），另外一种是AOF（append only file）持久化（原理是将Reids的操作日志以追加的方式写入文件）。那么这两种持久化方式有什么区别呢，改如何选择呢？网上看了大多数都是介绍这两种方式怎么配置，怎么使用，就是没有介绍二者的区别，在什么应用场景下使用。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2二者的区别\" class=\"anchor\" href=\"#2%E4%BA%8C%E8%80%85%E7%9A%84%E5%8C%BA%E5%88%AB\"\u003E\u003C/a\u003E2、二者的区别\u003C/h3\u003E\n\u003Cp\u003ERDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘，实际操作过程是fork一个子进程，先将数据集写入临时文件，写入成功后，再替换之前的文件，用二进制压缩存储。\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1122/150134_65067f70_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cp\u003EAOF持久化以日志的形式记录服务器所处理的每一个写、删除操作，查询操作不会记录，以文本的方式记录，可以打开文件看到详细的操作记录。\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1122/150235_9c3cbd44_907621.png\" alt=\"\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3二者优缺点\" class=\"anchor\" href=\"#3%E4%BA%8C%E8%80%85%E4%BC%98%E7%BC%BA%E7%82%B9\"\u003E\u003C/a\u003E3、二者优缺点\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"rdb存在哪些优势呢\" class=\"anchor\" href=\"#rdb%E5%AD%98%E5%9C%A8%E5%93%AA%E4%BA%9B%E4%BC%98%E5%8A%BF%E5%91%A2\"\u003E\u003C/a\u003ERDB存在哪些优势呢？\u003C/h4\u003E\n\u003Cp\u003E1). 一旦采用该方式，那么你的整个Redis数据库将只包含一个文件，这对于文件备份而言是非常完美的。比如，你可能打算每个小时归档一次最近24小时的数据，同时还要每天归档一次最近30天的数据。通过这样的备份策略，一旦系统出现灾难性故障，我们可以非常容易的进行恢复。\u003C/p\u003E\n\u003Cp\u003E2). 对于灾难恢复而言，RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。\u003C/p\u003E\n\u003Cp\u003E3). 性能最大化。对于Redis的服务进程而言，在开始持久化时，它唯一需要做的只是fork出子进程，之后再由子进程完成这些持久化的工作，这样就可以极大的避免服务进程执行IO操作了。\u003C/p\u003E\n\u003Cp\u003E4). 相比于AOF机制，如果数据集很大，RDB的启动效率会更高。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"rdb又存在哪些劣势呢\" class=\"anchor\" href=\"#rdb%E5%8F%88%E5%AD%98%E5%9C%A8%E5%93%AA%E4%BA%9B%E5%8A%A3%E5%8A%BF%E5%91%A2\"\u003E\u003C/a\u003ERDB又存在哪些劣势呢？\u003C/h4\u003E\n\u003Cp\u003E1). 如果你想保证数据的高可用性，即最大限度的避免数据丢失，那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象，此前没有来得及写入磁盘的数据都将丢失。\u003C/p\u003E\n\u003Cp\u003E2). 由于RDB是通过fork子进程来协助完成数据持久化工作的，因此，如果当数据集较大时，可能会导致整个服务器停止服务几百毫秒，甚至是1秒钟。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"aof的优势有哪些呢\" class=\"anchor\" href=\"#aof%E7%9A%84%E4%BC%98%E5%8A%BF%E6%9C%89%E5%93%AA%E4%BA%9B%E5%91%A2\"\u003E\u003C/a\u003EAOF的优势有哪些呢？\u003C/h4\u003E\n\u003Cp\u003E1). 该机制可以带来更高的数据安全性，即数据持久性。Redis中提供了3中同步策略，即每秒同步、每修改同步和不同步。事实上，每秒同步也是异步完成的，其效率也是非常高的，所差的是一旦系统出现宕机现象，那么这一秒钟之内修改的数据将会丢失。而每修改同步，我们可以将其视为同步持久化，即每次发生的数据变化都会被立即记录到磁盘中。可以预见，这种方式在效率上是最低的。至于无同步，无需多言，我想大家都能正确的理解它。\u003C/p\u003E\n\u003Cp\u003E2). 由于该机制对日志文件的写入操作采用的是append模式，因此在写入过程中即使出现宕机现象，也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题，不用担心，在Redis下一次启动之前，我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。\u003C/p\u003E\n\u003Cp\u003E3). 如果日志过大，Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中，同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。\u003C/p\u003E\n\u003Cp\u003E4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上，我们也可以通过该文件完成数据的重建。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"aof的劣势有哪些呢\" class=\"anchor\" href=\"#aof%E7%9A%84%E5%8A%A3%E5%8A%BF%E6%9C%89%E5%93%AA%E4%BA%9B%E5%91%A2\"\u003E\u003C/a\u003EAOF的劣势有哪些呢？\u003C/h4\u003E\n\u003Cp\u003E1). 对于相同数量的数据集而言，AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。\u003C/p\u003E\n\u003Cp\u003E2). 根据同步策略的不同，AOF在运行效率上往往会慢于RDB。总之，每秒同步策略的效率是比较高的，同步禁用策略的效率和RDB一样高效。\u003C/p\u003E\n\u003Cp\u003E二者选择的标准，就是看系统是愿意牺牲一些性能，换取更高的缓存一致性（aof），还是愿意写操作频繁的时候，不启用备份来换取更高的性能，待手动运行save的时候，再做备份（rdb）。rdb这个就更有些 eventually consistent的意思了。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4常用配置\" class=\"anchor\" href=\"#4%E5%B8%B8%E7%94%A8%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E4、常用配置\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"rdb持久化配置快照方式测试环境可以使用\" class=\"anchor\" href=\"#rdb%E6%8C%81%E4%B9%85%E5%8C%96%E9%85%8D%E7%BD%AE%E5%BF%AB%E7%85%A7%E6%96%B9%E5%BC%8F%E6%B5%8B%E8%AF%95%E7%8E%AF%E5%A2%83%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8\"\u003E\u003C/a\u003ERDB持久化配置（快照方式，测试环境可以使用）\u003C/h4\u003E\n\u003Cp\u003ERedis会将数据集的快照dump到dump.rdb文件中。此外，我们也可以通过配置文件来修改Redis服务器dump快照的频率，在打开6379.conf文件之后，我们搜索save，可以看到下面的配置信息：\u003C/p\u003E\n\u003Cp\u003Esave 900 1              #在900秒(15分钟)之后，如果至少有1个key发生变化，则dump内存快照。\u003C/p\u003E\n\u003Cp\u003Esave 300 10            #在300秒(5分钟)之后，如果至少有10个key发生变化，则dump内存快照。\u003C/p\u003E\n\u003Cp\u003Esave 60 10000        #在60秒(1分钟)之后，如果至少有10000个key发生变化，则dump内存快照。\u003C/p\u003E\n\u003Ch4\u003E\n\u003Ca id=\"aof持久化配置生成环境使用建议配置为always\" class=\"anchor\" href=\"#aof%E6%8C%81%E4%B9%85%E5%8C%96%E9%85%8D%E7%BD%AE%E7%94%9F%E6%88%90%E7%8E%AF%E5%A2%83%E4%BD%BF%E7%94%A8%E5%BB%BA%E8%AE%AE%E9%85%8D%E7%BD%AE%E4%B8%BAalways\"\u003E\u003C/a\u003EAOF持久化配置（生成环境使用，建议配置为always）\u003C/h4\u003E\n\u003Cp\u003E在Redis的配置文件中存在三种同步方式，它们分别是：\u003C/p\u003E\n\u003Cp\u003Eappendfsync always     #每次有数据修改发生时都会写入AOF文件。\u003C/p\u003E\n\u003Cp\u003Eappendfsync everysec  #每秒钟同步一次，该策略为AOF的缺省策略。\u003C/p\u003E\n\u003Cp\u003Eappendfsync no          #从不同步。高效但是数据不会被持久化。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5参考资料\" class=\"anchor\" href=\"#5%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E5、参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"http://blog.csdn.net/jackpk/article/details/30073097\"\u003Ehttp://blog.csdn.net/jackpk/article/details/30073097\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://www.jb51.net/article/65264.htm\"\u003Ehttp://www.jb51.net/article/65264.htm\u003C/a\u003E\u003C/p\u003E","680340":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo父子类共用变量\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E7%88%B6%E5%AD%90%E7%B1%BB%E5%85%B1%E7%94%A8%E5%8F%98%E9%87%8F\"\u003E\u003C/a\u003E1. 示例demo（父子类共用变量）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class SyncDubbo2 {\n\n\tstatic class Main {\n\t\tpublic int i = 10;\n\t\tpublic synchronized void operationSup(){\n\t\t\ttry {\n\t\t\t\ti--;\n\t\t\t\tSystem.out.println(\"Main print i = \" + i);\n\t\t\t\tThread.sleep(100);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tstatic class Sub extends Main {\n\t\tpublic synchronized void operationSub(){\n\t\t\ttry {\n\t\t\t\twhile(i \u0026gt; 0) {\n\t\t\t\t\ti--;\n\t\t\t\t\tSystem.out.println(\"Sub print i = \" + i);\n\t\t\t\t\tThread.sleep(100);\t\t\n\t\t\t\t\tthis.operationSup();\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tSub sub = new Sub();\n\t\t\t\tsub.operationSub();\n\t\t\t}\n\t\t});\n\t\t\n\t\tt1.start();\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E","735460":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建一个可缓存线程池，应用中存在的线程数可以无限大\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic static ExecutorService newCachedThreadPool() {\n        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,\n                                      60L, TimeUnit.SECONDS,\n                                      new SynchronousQueue\u0026lt;Runnable\u0026gt;());\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E主要问题是线程数最大数是Integer.MAX_VALUE，可能会创建数量非常多的线程，甚至OOM。\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n/**\n * 测试CachedThreadPool\n */\npublic static void testCachedThreadPool() {\n    ExecutorService executorService = Executors.newCachedThreadPool();\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.execute(new TempTask(i));\n    }\n    executorService.shutdown();\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/111139_e1d60157_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","822874":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0930/152203_5f7edb7c_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage bhz.fxz.seq;\n\n\nimport bhz.fxz.ring.OrderEvent;\nimport com.lmax.disruptor.YieldingWaitStrategy;\nimport com.lmax.disruptor.dsl.Disruptor;\nimport com.lmax.disruptor.dsl.ProducerType;\n\nimport java.util.concurrent.ExecutionException;\nimport java.util.concurrent.ExecutorService;\nimport java.util.concurrent.Executors;\nimport java.util.concurrent.Future;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/30\n */\npublic class SeqMain {\n    /**\n     * ringbuffer 缓存大小\n     */\n    private final static int BUFFER_SIZE = 1024;\n\n    /**\n     * 线程池大小\n     */\n    private final static int THREAD_SIZE = 8;\n\n    /**\n     * 生产数量\n     */\n    private final static int LOOP = 1;\n\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n\n        long beginTime = System.currentTimeMillis();\n\n        // 0. 创建线程池\n        ExecutorService executorService = Executors.newFixedThreadPool(THREAD_SIZE);\n\n        // 1. 创建disruptor\n        Disruptor\u0026lt;OrderEvent\u0026gt; disruptor = new Disruptor\u0026lt;OrderEvent\u0026gt;(\n                () -\u0026gt; {\n                    return new OrderEvent();\n                },\n                BUFFER_SIZE,\n                executorService,\n                ProducerType.SINGLE,\n                new YieldingWaitStrategy()\n        );\n\n        // 2. 设置消费顺序（直线顺序消费）\n        OrderHandler1 h1 = new OrderHandler1();\n        OrderHandler2 h2 = new OrderHandler2();\n        OrderHandler3 h3 = new OrderHandler3();\n        OrderHandler4 h4 = new OrderHandler4();\n        OrderHandler5 h5 = new OrderHandler5();\n        OrderHandler6 h6 = new OrderHandler6();\n\n        /**\n         *  模型\n         *\n         *          H2  --  H4\n         *       /              \\\n         *   H1                    H6\n         *       \\              /\n         *          H3  --  H5\n         */\n        disruptor.handleEventsWith(h1);\n        disruptor.after(h1).handleEventsWith(h2, h3);\n        disruptor.after(h2).handleEventsWith(h4);\n        disruptor.after(h3).handleEventsWith(h5);\n        disruptor.after(h4, h5).handleEventsWith(h6);\n\n\n        // 3. 启动\n        disruptor.start();\n\n        // 4. 生产数据\n        Future\u0026lt;?\u0026gt; future = executorService.submit(() -\u0026gt; {\n            for (int i = 0; i \u0026lt; LOOP; i++) {\n                disruptor.publishEvent((OrderEvent event, long sequence) -\u0026gt; {\n                    event.setName(\"初始化订单\");\n                    System.out.println(\"初始化订单\");\n                });\n            }\n            return null;\n        });\n\n        // 5. 保证数据生成完成\n        future.get();\n\n        // 6. 关闭资源\n        disruptor.shutdown();\n        executorService.shutdown();\n\n        System.out.println(\"耗时：\" + (System.currentTimeMillis() - beginTime));\n    }\n}\n\n\u003C/code\u003E\u003C/pre\u003E","987026":"\u003Ch4\u003E\n\u003Ca id=\"1-下载git源码\" class=\"anchor\" href=\"#1-%E4%B8%8B%E8%BD%BDgit%E6%BA%90%E7%A0%81\"\u003E\u003C/a\u003E1. 下载git源码\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Ehttps://github.com/git/git/releases\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"2-解压\" class=\"anchor\" href=\"#2-%E8%A7%A3%E5%8E%8B\"\u003E\u003C/a\u003E2. 解压\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf git-2.17.0.tar.gz \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"3-编译安装\" class=\"anchor\" href=\"#3-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E3. 编译安装\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装依赖\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum -y install curl-devel expat-devel gettext-devel openssl-devel zlib zlib-devel gcc perl-ExtUtils-MakeMaker wget\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E编译\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd git-2.17.0\nsudo make prefix=/usr/local/git all\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esudo make prefix=/usr/local/git install\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"4-git-基础配置\" class=\"anchor\" href=\"#4-git-%E5%9F%BA%E7%A1%80%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E4. git 基础配置\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置用户名\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global user.name \"yourname\"\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E用户名密码同步\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit clone http://username:password@127.0.0.1/res/res.git\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E列表内容\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global user.email \"youremail\"\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E忽略 win or linux 换行符转换\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global core.autocrlf false\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E编码配置\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Egit config --global gui.encoding utf-8\ngit config --global core.quotepath off\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch4\u003E\n\u003Ca id=\"5-ssh-for-码云\" class=\"anchor\" href=\"#5-ssh-for-%E7%A0%81%E4%BA%91\"\u003E\u003C/a\u003E5. SSH for 码云\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E生成ssh公钥\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Essh-keygen -t rsa -C \"413916057@qq.com\"  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E三次回车即可生成 ssh key\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E添加秘钥\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Essh-add ~/.ssh/xxx_rsa  #添加秘钥\n#ssh-add -d  ~/.ssh/xxx_rsa # 删除key\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E码云添加公钥\n查看你的 public key，并把他添加到码云（Gitee.com） SSH key添加地址:\u003Ca href=\"https://gitee.com/profile/sshkeys\"\u003Ehttps://gitee.com/profile/sshkeys\u003C/a\u003E)\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1204/140016_6557585d_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Essh -T git@github.com\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E设置成功，能看到：\u003C/p\u003E\n\u003Cp\u003EHi xxxxx! You've successfully authenticated, but GitHub does not provide shell access.\u003C/p\u003E","1024065":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/xuezhigu/p/6652835.html\"\u003ECentOS7中关闭firewall，并使用iptables管理防火墙\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2关闭默认的firewall防火墙\" class=\"anchor\" href=\"#2%E5%85%B3%E9%97%AD%E9%BB%98%E8%AE%A4%E7%9A%84firewall%E9%98%B2%E7%81%AB%E5%A2%99\"\u003E\u003C/a\u003E2.关闭默认的firewall防火墙\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 关闭防火墙\nsystemctl stop firewalld.service \n\n# 关闭开机启动\nsystemctl disable firewalld.service \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-开启iptables\" class=\"anchor\" href=\"#3-%E5%BC%80%E5%90%AFiptables\"\u003E\u003C/a\u003E3. 开启iptables\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# （根据centOS7的版本和内核，有些版本已经装过，可以跳过此命令）\nyum install iptables \nyum install iptables-services\n\nservice iptables restart\n\n# 设置开机自启\nchkconfig iptables on 或者systemctl enable iptables.service \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-编辑防火墙文件开启了2122803306端口\" class=\"anchor\" href=\"#4-%E7%BC%96%E8%BE%91%E9%98%B2%E7%81%AB%E5%A2%99%E6%96%87%E4%BB%B6%E5%BC%80%E5%90%AF%E4%BA%862122803306%E7%AB%AF%E5%8F%A3\"\u003E\u003C/a\u003E4. 编辑防火墙文件（开启了21,22,80,3306端口）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/sysconfig/iptables\n \n# sampleconfiguration for iptables service \n# # you can edit thismanually or use system-config-firewall \n# # please do not askus to add additional ports/services to this default configuration \n*filter \n:INPUT ACCEPT [0:0] \n:FORWARD ACCEPT [0:0] \n:OUTPUT ACCEPT [0:0] \n-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT \n-A INPUT -p icmp -j ACCEPT \n-A INPUT -i lo -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT \n-A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT \n-A INPUT -j REJECT --reject-with icmp-host-prohibited \n-A FORWARD -j REJECT --reject-with icmp-host-prohibited \nCOMMIT \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-添加防火墙命令\" class=\"anchor\" href=\"#5-%E6%B7%BB%E5%8A%A0%E9%98%B2%E7%81%AB%E5%A2%99%E5%91%BD%E4%BB%A4\"\u003E\u003C/a\u003E5. 添加防火墙命令\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-查看本机关于iptables的设置情况\" class=\"anchor\" href=\"#6-%E6%9F%A5%E7%9C%8B%E6%9C%AC%E6%9C%BA%E5%85%B3%E4%BA%8Eiptables%E7%9A%84%E8%AE%BE%E7%BD%AE%E6%83%85%E5%86%B5\"\u003E\u003C/a\u003E6. 查看本机关于IPTABLES的设置情况\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eiptables -L -n\n\u003C/code\u003E\u003C/pre\u003E","995533":"\u003Ch3\u003E\n\u003Ca id=\"redis-有序集合sorted-set\" class=\"anchor\" href=\"#redis-%E6%9C%89%E5%BA%8F%E9%9B%86%E5%90%88sorted-set\"\u003E\u003C/a\u003Eredis 有序集合(sorted set)\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003Eredis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E有序集合的成员是唯一的,但分数(score)却可以重复。\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E集合是通过哈希表实现的，所以添加，删除，查找的复杂度都是o(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Ezadd key score1 member1 [score2 member2]\u003C/td\u003E\n\u003Ctd\u003E向有序集合添加一个或多个成员，或者更新已存在成员的分数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Ezcard key\u003C/td\u003E\n\u003Ctd\u003E获取有序集合的成员数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Ezcount key min max\u003C/td\u003E\n\u003Ctd\u003E计算在有序集合中指定区间分数的成员数\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Ezincrby key increment member\u003C/td\u003E\n\u003Ctd\u003E有序集合中对指定成员的分数加上增量 increment\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Ezinterstore destination numkeys key [key ...]\u003C/td\u003E\n\u003Ctd\u003E计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Ezlexcount key min max\u003C/td\u003E\n\u003Ctd\u003E在有序集合中计算指定字典区间内成员数量\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Ezrange key start stop [withscores]\u003C/td\u003E\n\u003Ctd\u003E通过索引区间返回有序集合成指定区间内的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ezrangebylex key min max [limit offset count]\u003C/td\u003E\n\u003Ctd\u003E通过字典区间返回有序集合的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Ezrangebyscore key min max [withscores] [limit]\u003C/td\u003E\n\u003Ctd\u003E通过分数返回有序集合指定区间内的成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Ezrank key member\u003C/td\u003E\n\u003Ctd\u003E返回有序集合中指定成员的索引\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Ezrem key member [member ...]\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中的一个或多个成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Ezremrangebylex key min max\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中给定的字典区间的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Ezremrangebyrank key start stop\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中给定的排名区间的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Ezremrangebyscore key min max\u003C/td\u003E\n\u003Ctd\u003E移除有序集合中给定的分数区间的所有成员\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Ezrevrange key start stop [withscores]\u003C/td\u003E\n\u003Ctd\u003E返回有序集中指定区间内的成员，通过索引，分数从高到底\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Ezrevrangebyscore key max min [withscores]\u003C/td\u003E\n\u003Ctd\u003E返回有序集中指定分数区间内的成员，分数从高到低排序\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E17\u003C/td\u003E\n\u003Ctd\u003Ezrevrank key member\u003C/td\u003E\n\u003Ctd\u003E返回有序集合中指定成员的排名，有序集成员按分数值递减(从大到小)排序\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E18\u003C/td\u003E\n\u003Ctd\u003Ezscore key member\u003C/td\u003E\n\u003Ctd\u003E返回有序集中，成员的分数值\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E19\u003C/td\u003E\n\u003Ctd\u003Ezunionstore destination numkeys key [key ...]\u003C/td\u003E\n\u003Ctd\u003E计算给定的一个或多个有序集的并集，并存储在新的 key 中\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E20\u003C/td\u003E\n\u003Ctd\u003Ezscan key cursor [match pattern] [count count]\u003C/td\u003E\n\u003Ctd\u003E迭代有序集合中的元素（包括元素成员和元素分值）\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","680382":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo异常处理\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E5%BC%82%E5%B8%B8%E5%A4%84%E7%90%86\"\u003E\u003C/a\u003E1. 示例demo（异常处理）\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E不跳出循环\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class SyncException {\n\n\tprivate int i = 0;\n\tpublic synchronized void operation(){\n\t\twhile(true){\n\t\t\ttry {\n\t\t\t\ti++;\n\t\t\t\tThread.sleep(100);\n\t\t\t\tSystem.out.println(Thread.currentThread().getName() + \" , i = \" + i);\n\t\t\t\tif(i == 20){\n\t\t\t\t\tInteger.parseInt(\"a\");\n\t\t\t\t}\n\t\t\t} catch (Exception e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal SyncException se = new SyncException();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tse.operation();\n\t\t\t}\n\t\t},\"t1\");\n\t\tt1.start();\n\t}\n\t\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E跳出循环，可以抛出异常\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class SyncException {\n\n\tprivate int i = 0;\n\tpublic synchronized void operation(){\n\t\twhile(true){\n\t\t\ttry {\n\t\t\t\ti++;\n\t\t\t\tThread.sleep(100);\n\t\t\t\tSystem.out.println(Thread.currentThread().getName() + \" , i = \" + i);\n\t\t\t\tif(i == 20){\n\t\t\t\t\t//Integer.parseInt(\"a\");\n\t\t\t\t\tthrow new RuntimeException();\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal SyncException se = new SyncException();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tse.operation();\n\t\t\t}\n\t\t},\"t1\");\n\t\tt1.start();\n\t}\n\t\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E","735480":"\u003Ch3\u003E\n\u003Ca id=\"1-说明\" class=\"anchor\" href=\"#1-%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E1. 说明：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E创建一个定长线程池，支持定时及周期性任务执行。延迟执行示例代码如下：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-方法签名\" class=\"anchor\" href=\"#2-%E6%96%B9%E6%B3%95%E7%AD%BE%E5%90%8D\"\u003E\u003C/a\u003E2. 方法签名：\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic ScheduledThreadPoolExecutor(int corePoolSize) {\n        super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,\n              new DelayedWorkQueue());\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E主要问题是线程数最大数是Integer.MAX_VALUE，可能会创建数量非常多的线程，甚至OOM。\u003C/strong\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-示例demo\" class=\"anchor\" href=\"#3-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E3. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eprivate static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n/**\n * 测试线程类\n */\nstatic class TempTask implements Runnable {\n\n    private int taskId;\n\n    public TempTask(int taskId) {\n        this.taskId = taskId;\n    }\n\n    @Override\n    public void run() {\n        System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n        try {\n            Thread.sleep(1000);\n        } catch (InterruptedException e) {\n            e.printStackTrace();\n        }\n    }\n}\n\n/**\n * 测试ScheduledThreadPool\n */\npublic static void testScheduledThreadPool() {\n    ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);\n    System.out.println(\"准备开始时间：\" + format.format(new Date()));\n    for (int i = 1; i \u0026lt;= 4; i++) {\n        executorService.schedule(new TempTask(i)  , 3 , TimeUnit.SECONDS);\n    }\n    executorService.shutdown();\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/112105_9aee4d78_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E","987027":"\u003Ch3\u003E\n\u003Ca id=\"1下载安装文件\" class=\"anchor\" href=\"#1%E4%B8%8B%E8%BD%BD%E5%AE%89%E8%A3%85%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E1.下载安装文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz解压安装：\n\ntar -zxvf apache-maven-3.3.9-bin.tar.gz\n\nmv apache-maven-3.3.9 maven (这一步骤可省略，主要是为了后面方便操作)配置环境变量\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-使用vim编辑etcprofile文件\" class=\"anchor\" href=\"#2-%E4%BD%BF%E7%94%A8vim%E7%BC%96%E8%BE%91etcprofile%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E2. 使用vim编辑/etc/profile文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E在/etc/profile文件末尾增加以下配置：     \nM2_HOME=/opt/tyrone/maven （注意这里是maven的安装路径）\nexport PATH=${M2_HOME}/bin:${PATH}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-重载etcprofile这个文件\" class=\"anchor\" href=\"#3-%E9%87%8D%E8%BD%BDetcprofile%E8%BF%99%E4%B8%AA%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E3. 重载/etc/profile这个文件\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Esource /etc/profile\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-检验maven是否安装成功\" class=\"anchor\" href=\"#4-%E6%A3%80%E9%AA%8Cmaven%E6%98%AF%E5%90%A6%E5%AE%89%E8%A3%85%E6%88%90%E5%8A%9F\"\u003E\u003C/a\u003E4. 检验maven是否安装成功\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Emvn -v\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/094826_66db254c_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-创建仓库目录\" class=\"anchor\" href=\"#5-%E5%88%9B%E5%BB%BA%E4%BB%93%E5%BA%93%E7%9B%AE%E5%BD%95\"\u003E\u003C/a\u003E5. 创建仓库目录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[fxz@localhost repository]$ cd /usr/local/deve/soft/maven-3.5.3/\n[fxz@localhost maven-3.5.3]$ mkdir repository\n[fxz@localhost maven-3.5.3]$ cd repository/\n[fxz@localhost repository]$ pwd\n/usr/local/deve/soft/maven-3.5.3/repository\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6-修改settingxml\" class=\"anchor\" href=\"#6-%E4%BF%AE%E6%94%B9settingxml\"\u003E\u003C/a\u003E6. 修改setting.xml\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 配置仓库地址\n\u0026lt;localRepository\u0026gt;/usr/local/deve/soft/maven-3.5.3/repository\u0026lt;/localRepository\u0026gt;\n\n# 配置私仓地址\n\u0026lt;mirror\u0026gt;\n        \u0026lt;id\u0026gt;nexus-aliyun\u0026lt;/id\u0026gt;\n        \u0026lt;mirrorOf\u0026gt;*\u0026lt;/mirrorOf\u0026gt;\n        \u0026lt;name\u0026gt;Nexus aliyun\u0026lt;/name\u0026gt;\n        \u0026lt;url\u0026gt;http://maven.aliyun.com/nexus/content/groups/public\u0026lt;/url\u0026gt;\n    \u0026lt;/mirror\u0026gt;\n\n     \u0026lt;mirror\u0026gt;\n        \u0026lt;id\u0026gt;nexus-osc\u0026lt;/id\u0026gt;\n        \u0026lt;mirrorOf\u0026gt;central\u0026lt;/mirrorOf\u0026gt;\n        \u0026lt;name\u0026gt;Nexus osc\u0026lt;/name\u0026gt;\n        \u0026lt;url\u0026gt;http://192.168.1.250:8081/nexus/content/groups/public\u0026lt;/url\u0026gt;\n    \u0026lt;/mirror\u0026gt;\n    \u0026lt;mirror\u0026gt;\n        \u0026lt;id\u0026gt;nexus-osc-thirdparty\u0026lt;/id\u0026gt;\n        \u0026lt;mirrorOf\u0026gt;thirdparty\u0026lt;/mirrorOf\u0026gt;\n        \u0026lt;name\u0026gt;Nexus osc thirdparty\u0026lt;/name\u0026gt;\n        \u0026lt;url\u0026gt;http://192.168.1.250:8081/nexus/content/repositories/thirdparty/\u0026lt;/url\u0026gt;\n    \u0026lt;/mirror\u0026gt;\n\n# 配置profile\n\n \u0026lt;id\u0026gt;jdk-1.8\u0026lt;/id\u0026gt;\n         \u0026lt;activation\u0026gt;\n             \u0026lt;activeByDefault\u0026gt;true\u0026lt;/activeByDefault\u0026gt;\n             \u0026lt;jdk\u0026gt;1.8\u0026lt;/jdk\u0026gt;\n          \u0026lt;/activation\u0026gt;\n          \u0026lt;properties\u0026gt;\n              \u0026lt;maven.compiler.source\u0026gt;1.8\u0026lt;/maven.compiler.source\u0026gt;\n              \u0026lt;maven.compiler.target\u0026gt;1.8\u0026lt;/maven.compiler.target\u0026gt;\n              \u0026lt;maven.compiler.compilerVersion\u0026gt;1.8\u0026lt;/maven.compiler.compilerVersion\u0026gt;\n          \u0026lt;/properties\u0026gt;\n\n      \u0026lt;repositories\u0026gt;\n        \u0026lt;repository\u0026gt;\n          \u0026lt;id\u0026gt;nexus\u0026lt;/id\u0026gt;\n          \u0026lt;name\u0026gt;OSChina Central\u0026lt;/name\u0026gt;\n          \u0026lt;url\u0026gt;http://192.168.1.250:8081/nexus/content/groups/public\u0026lt;/url\u0026gt;\n        \u0026lt;/repository\u0026gt;\n\n        \u0026lt;repository\u0026gt;\n            \u0026lt;id\u0026gt;sonatype-nexus-snapshots\u0026lt;/id\u0026gt;\n            \u0026lt;url\u0026gt;https://oss.sonatype.org/content/repositories/snapshots\u0026lt;/url\u0026gt;\n            \u0026lt;releases\u0026gt;\n                \u0026lt;enabled\u0026gt;false\u0026lt;/enabled\u0026gt;\n            \u0026lt;/releases\u0026gt;\n            \u0026lt;snapshots\u0026gt;\n                \u0026lt;enabled\u0026gt;true\u0026lt;/enabled\u0026gt;\n            \u0026lt;/snapshots\u0026gt;\n        \u0026lt;/repository\u0026gt;\n      \u0026lt;/repositories\u0026gt;\n\n\u0026lt;pluginRepositories\u0026gt;\n        \u0026lt;pluginRepository\u0026gt;\n          \u0026lt;id\u0026gt;nexus2\u0026lt;/id\u0026gt;\n          \u0026lt;name\u0026gt;local private nexus\u0026lt;/name\u0026gt;\n          \u0026lt;url\u0026gt; http://192.168.1.250:8081/nexus/content/groups/public \u0026lt;/url\u0026gt;\n        \u0026lt;/pluginRepository\u0026gt;\n      \u0026lt;/pluginRepositories\u0026gt;\n\n\n\n\n\u003C/code\u003E\u003C/pre\u003E","995289":"\u003Cpre\u003E\u003Ccode\u003Epackage com.i84.insect.core.config.redis;\n\nimport com.xiaoleilu.hutool.date.DateUtil;\nimport org.apache.log4j.Logger;\nimport org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.data.redis.connection.RedisConnection;\nimport org.springframework.data.redis.core.RedisCallback;\nimport org.springframework.data.redis.core.RedisTemplate;\n\nimport java.util.*;\n\n/**\n * 类描述    : redis操作类，用于缓存 \u0026lt;br/\u0026gt;\n * 项目名称  : xlauch 项目\u0026lt;br/\u0026gt;\n * 类名称    : RedisManager \u0026lt;br/\u0026gt;\n *\n * @author 伊凡  413916057@qq.com\u0026lt;br/\u0026gt;\n *         创建日期: 2017/11/8 14:54  \u0026lt;br/\u0026gt;\n * @version 0.1\n */\n@Configuration\npublic class RedisManager {\n\n    private static final Logger log = Logger.getLogger(RedisManager.class);\n\n    @Autowired\n    private RedisTemplate\u0026lt;String, String\u0026gt; redisTemplate;\n\n    /**\n     * 生成id专用\n     */\n    public static final String ID = \"id\";\n\n    /********************************** 类型：键 *********************************/\n    /**\n     * 类型：键\n     * 删除给定的一个 key\n     * @param key\n     * @return\n     */\n    public void del(final String key) {\n        redisTemplate.delete(key);\n    }\n\n    /**\n     * 类型：键\n     * 批量删除键值\n     * @param prestr\n     * @return\n     */\n    public void batchDel(final String prestr){\n        Set\u0026lt;String\u0026gt; set = keys(prestr +\"*\");\n        redisTemplate.delete(set);\n    }\n\n    /**\n     * 类型：键\n     * 查找所有符合给定模式 pattern 的 key\n     * KEYS * 匹配数据库中所有 key\n     * @param pattern\n     * @return\n     */\n    public Set\u0026lt;String\u0026gt; keys(final String pattern) {\n        return redisTemplate.keys(pattern);\n    }\n\n    /**\n     * 类型：键\n     * 检查给定 key 是否存在\n     * @param key\n     * @return\n     */\n    public Boolean exists(final String key) {\n        return redisTemplate.execute(new RedisCallback\u0026lt;Boolean\u0026gt;() {\n            @Override\n            public Boolean doInRedis(RedisConnection redisConnection) {\n                return redisConnection.exists(key.getBytes());\n            }\n        });\n    }\n\n\n    /********************************** 类型：字符串 *********************************/\n\n    /**\n     * 类型：字符串\n     * 将字符串值 value 关联到 key\n     * 如果 key 已经持有其他值， SET 就覆写旧值，无视类型\n     * @param key\n     * @param value\n     */\n    public void set(final String key, final String value) {\n        redisTemplate.opsForValue().set(key, value);\n    }\n\n    /**\n     * 如果 key 已经存在并且是一个字符串， APPEND 命令将 value 追加到 key 原来的值的末尾。\n     * 如果 key 不存在， APPEND 就简单地将给定 key 设为 value ，就像执行 SET key value 一样。\n     *\n     * @param key the key\n     * @param appendValue the append value\n     */\n    public void append(final String key, final String appendValue) {\n        redisTemplate.opsForValue().append(key, appendValue);\n    }\n\n    /**\n     *  类型：字符串\n     *  将字符串值 value 关联到 key 并设置失效时间\n     * @param key\n     * @param value\n     * @param expireTime\n     */\n    public void setWithExp(final String key, final String value, final Date expireTime) {\n        redisTemplate.opsForValue().set(key, value);\n        redisTemplate.expireAt(key, expireTime);\n    }\n\n    /**\n     * 类型：字符串\n     * 返回 key 所关联的字符串值\n     * @param key\n     * @return\n     */\n    public String get(final String key) {\n        return redisTemplate.opsForValue().get(key);\n    }\n\n    /**\n     * 类型：字符串\n     * 创建数据id，所有额都通过此方法创建\n     *\n     * @return\n     */\n    public long createID() {\n        return redisTemplate.opsForValue().increment(ID, 1);\n    }\n\n    /**\n     * 类型：字符串\n     * 创建相应模块的自增长id\n     * @author\n     * Jun 23, 2014 11:46:00 AM\n     */\n    public long createModuleID(final String module){\n        Long value = redisTemplate.opsForValue().increment(module, 1);\n        redisTemplate.expireAt(module, DateUtil.offsetMinute(new Date(), 1));\n        return value;\n    }\n\n    /**\n     * 类型：字符串\n     * 用于统计当天的短信数\n     * key smscnt:当前日期:手机号 如：smscnt:20160115:12345678901\n     * unixTime 当天23:59:59的unix时间戳\n     * @author\n     * Jun 23, 2014 11:46:00 AM\n     */\n    public long incrWithExpire(final String key, final Date date){\n        Long value = redisTemplate.opsForValue().increment(key, 1);\n        redisTemplate.expireAt(key, date);\n        return value;\n    }\n\n    /**\n     * 类型：字符串\n     * +value的和\n     * @param key\n     * @param value\n     * @return\n     */\n    public long incrBy(final String key, final long value) {\n        Long value1 = redisTemplate.opsForValue().increment(key, value);\n        return value1;\n    }\n\n    /********************************** 类型：hash *********************************/\n    /**\n     * 类型：hash\n     * 将哈希表 key 中的域 field 的值设为 value\n     * @param key\n     * @param field\n     * @param value\n     */\n    public void hset(final String key, final String field, final String value) {\n        redisTemplate.opsForHash().put(key, field, value);\n    }\n\n    /**\n     * 类型：hash\n     * 返回哈希表 key 中给定域 field 的值\n     * @param key\n     * @param field\n     * @return\n     */\n    public String hget(final String key, final String field) {\n        if (redisTemplate.opsForHash().get(key, field) != null) {\n            return redisTemplate.opsForHash().get(key, field)+\"\";\n        }\n        return null ;\n    }\n\n    /**\n     * 类型：hash\n     * 返回哈希表 key 中，所有的域和值\n     * @param key\n     * @return\n     */\n    public Map\u0026lt;Object, Object\u0026gt; hgetAll(final String key) {\n        return redisTemplate.opsForHash().entries(key);\n    }\n\n    /**\n     * 类型：hash\n     * 查看哈希表 key 中，给定域 field 是否存在\n     * @param key\n     * @param field\n     * @return\n     */\n    public Boolean hexists(final String key, final String field) {\n        return redisTemplate.opsForHash().hasKey(key, field);\n    }\n\n    /**\n     * 类型：hash\n     * 返回哈希表 key 中域的数量\n     * @param key\n     * @return\n     */\n    public Long hlen(final String key){\n        return redisTemplate.opsForHash().size(key);\n    }\n\n    /**\n     * 类型：hash\n     * 删除哈希表 key 中的一个或多个指定域，不存在的域将被忽略\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long hdel(final String key, final String... members) {\n        return redisTemplate.opsForHash().delete(key, members);\n    }\n\n    /**\n     * 类型：hash\n     * 同时将多个 field-value (域-值)对设置到哈希表 key 中\n     * @param key\n     * @param map\n     */\n    public void hmset(final String key, final Map\u0026lt;String, String\u0026gt; map) {\n        if (map == null || map.size() == 0) {\n            return;\n        }\n        redisTemplate.opsForHash().putAll(key, map);\n    }\n\n    /**\n     * 类型：hash\n     * 为哈希表 key 中的域 field 的值加上增量 increment 。\n     * 增量也可以为负数，相当于对给定域进行减法操作。\n     * 如果 key 不存在，一个新的哈希表被创建并执行 HINCRBY 命令。\n     * 如果域 field 不存在，那么在执行命令前，域的值被初始化为 0 。\n     * 对一个储存字符串值的域 field 执行 HINCRBY 命令将造成一个错误。\n     * 本操作的值被限制在 64 位(bit)有符号数字表示之内。\n     *\n     * @param key the key\n     * @param field the field\n     * @param value the value\n     */\n    public Long hincrby(final String key, final String field, final long value) {\n        return redisTemplate.opsForHash().increment(key, field, value);\n    }\n\n    /********************************** 类型：set *********************************/\n    /**\n     * 类型：set\n     * 如果命令执行时，只提供了 key 参数，那么返回集合中的一个随机元素\n     * @param key\n     * @return\n     */\n    public String srandmember(final String key) {\n        return redisTemplate.execute(new RedisCallback\u0026lt;String\u0026gt;() {\n\n            @Override\n            public String doInRedis(RedisConnection redisConnection) {\n                return new String(redisConnection.sRandMember(key.getBytes()));\n            }\n        });\n    }\n\n    /**\n     * 类型：set\n     * 返回集合 key 中的所有成员\n     * @param key\n     * @return\n     */\n    public Set\u0026lt;byte[]\u0026gt; smembers(final String key) {\n        return redisTemplate.execute(new RedisCallback\u0026lt;Set\u0026lt;byte[]\u0026gt;\u0026gt;() {\n\n            @Override\n            public Set\u0026lt;byte[]\u0026gt; doInRedis(RedisConnection redisConnection) {\n                return redisConnection.sMembers(key.getBytes());\n            }\n        });\n    }\n\n    /**\n     * 类型：set\n     * 将一个或多个 member 元素加入到集合 key 当中，已经存在于集合的 member 元素将被忽略\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long sadd(final String key, final String... members) {\n        return redisTemplate.opsForSet().add(key, members);\n    }\n\n    /**\n     * 类型：set\n     * 移除集合 key 中的一个或多个 member 元素，不存在的 member 元素会被忽略\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long srem(final String key, final String... members) {\n        return redisTemplate.opsForSet().remove(key, members);\n    }\n\n    /**\n     * 类型：set\n     * 判断 member 元素是否集合 key 的成员\n     * @param key\n     * @param value\n     * @return\n     */\n    public Boolean sismember(final String key, final String value) {\n        return redisTemplate.opsForSet().isMember(key, value);\n    }\n\n    /**\n     * 类型：set\n     * 返回两个集合的全部成员，该集合是所有给定集合的交集。\n     * @param key1\n     * @param key2\n     * @return\n     */\n    public Set\u0026lt;String\u0026gt; sinter(final String key1, final String key2){\n        return redisTemplate.opsForSet().intersect(key1, key2);\n    }\n\n    /********************************** 类型：list *********************************/\n    /**\n     * 类型：list\n     * 返回列表 key 中指定区间内的元素，区间以偏移量 startIndex 和 endIndex 指定\n     * @param key\n     * @param startIndex\n     * @param endIndex\n     * @return\n     */\n    public List\u0026lt;String\u0026gt; lrange(final String key, final long startIndex, final long endIndex) {\n        return redisTemplate.opsForList().range(key, startIndex, endIndex);\n    }\n\n    /**\n     * 类型：list\n     * 返回列表 key所有元素\n     * @param key\n     * @return\n     */\n    public List\u0026lt;String\u0026gt; lrange(final String key) {\n        return redisTemplate.opsForList().range(key, 0, -1);\n    }\n\n    /**\n     * 类型：list\n     * 从头部删除一个元素,\n     * @param key\n     * @return\n     */\n    public String lpop(final String key) {\n        return redisTemplate.opsForList().leftPop(key);\n    }\n\n    /**\n     * 类型：list\n     * 将列表 key 下标为 index 的元素的值设置为 value\n     * @param key\n     * @param index\n     * @param value\n     * @return\n     */\n    public Boolean lset(final String key, final int index, final String value) {\n        redisTemplate.opsForList().set(key, index, value);\n        return true;\n    }\n\n    /**\n     * 类型：list\n     * 移除并返回列表 key 的尾元素\n     * @param key the key\n     * @return the string\n     */\n    public String rpop(final String key) {\n        return redisTemplate.opsForList().rightPop(key);\n    }\n\n    /**\n     * 类型：list\n     * 根据参数 count 的值，移除列表中与参数 value 相等的元素\n     * count \u0026gt; 0 : 从表头开始向表尾搜索，移除与 value 相等的元素，数量为 count\n     * count \u0026lt; 0 : 从表尾开始向表头搜索，移除与 value 相等的元素，数量为 count 的绝对值\n     * count = 0 : 移除表中所有与 value 相等的值\n     * @param key the key\n     * @param count the count\n     * @param value the value\n     * @return the long\n     */\n    public long lrem(final String key, final long count, final String value) {\n        return redisTemplate.opsForList().remove(key, count, value);\n    }\n\n    /**\n     * 类型：list\n     * 将一个或多个值 value 插入到列表 key 的表尾(最右边)\n     * @param key\n     * @param members\n     * @return\n     */\n    public Long rpush(final String key, final String... members) {\n        return redisTemplate.opsForList().rightPushAll(key, members);\n    }\n\n    /**\n     * 类型：list\n     * 返回列表 key 的长度\n     * @param key\n     * @return\n     */\n    public Long llen(final String key) {\n        return redisTemplate.opsForList().size(key);\n    }\n\n\n    /**\n     * 类型 ：list\n     * 将一个或多个值 value 插入到列表 key 的表头\n     *\n     * @param key the key\n     * @param values the values\n     * @return the size after push\n     */\n    public Long lpush(final String key, final String... values) {\n        return redisTemplate.opsForList().leftPushAll(key, values);\n    }\n\n    /********************************** 类型：server *********************************/\n    /**\n     * 类型：server\n     * 返回当前数据库的 key 的数量。\n     * @return\n     */\n    public long dbsize() {\n        return redisTemplate.execute(new RedisCallback\u0026lt;Long\u0026gt;() {\n\n            @Override\n            public Long doInRedis(RedisConnection redisConnection) {\n                return redisConnection.dbSize();\n            }\n        });\n    }\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E","684142":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo-字符对象变更锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo-%E5%AD%97%E7%AC%A6%E5%AF%B9%E8%B1%A1%E5%8F%98%E6%9B%B4%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo 字符对象变更锁\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ChangeLock {\n\n\tprivate String lock = \"lock\";\n\t\n\tprivate void method(){\n\t\tsynchronized (lock) {\n\t\t\ttry {\n\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"开始\");\n\t\t\t\tlock = \"change lock\";\n\t\t\t\tThread.sleep(2000);\n\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"结束\");\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\n\t\tfinal ChangeLock changeLock = new ChangeLock();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tchangeLock.method();\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tchangeLock.method();\n\t\t\t}\n\t\t},\"t2\");\n\t\tt1.start();\n\t\ttry {\n\t\t\tThread.sleep(100);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\tt2.start();\n\t}\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1线程先持有字符对象的Lock锁，并修改字符对象内容，导致lock发生变更，t2线程就无需等待t1执行，直接获得变更后的新锁\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例demo-bean对象变更锁\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8Bdemo-bean%E5%AF%B9%E8%B1%A1%E5%8F%98%E6%9B%B4%E9%94%81\"\u003E\u003C/a\u003E2. 示例demo bean对象变更锁\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class ModifyLock {\n\t\n\tprivate String name ;\n\tprivate int age ;\n\t\n\tpublic String getName() {\n\t\treturn name;\n\t}\n\tpublic void setName(String name) {\n\t\tthis.name = name;\n\t}\n\tpublic int getAge() {\n\t\treturn age;\n\t}\n\tpublic void setAge(int age) {\n\t\tthis.age = age;\n\t}\n\t\n\tpublic synchronized void changeAttributte(String name, int age) {\n\t\ttry {\n\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 开始\");\n\t\t\tthis.setName(name);\n\t\t\tthis.setAge(age);\n\t\t\t\n\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 修改对象内容为： \" \n\t\t\t\t\t+ this.getName() + \", \" + this.getAge());\n\t\t\t\n\t\t\tThread.sleep(2000);\n\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 结束\");\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal ModifyLock modifyLock = new ModifyLock();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmodifyLock.changeAttributte(\"张三\", 20);\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tmodifyLock.changeAttributte(\"李四\", 21);\n\t\t\t}\n\t\t},\"t2\");\n\t\t\n\t\tt1.start();\n\t\ttry {\n\t\t\tThread.sleep(100);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\tt2.start();\n\t}\n\t\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0823/092107_d7c91f85_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E虽然t1在获得\"modifyLock\"对象lock后，对其属性值进行修改，但是同一对象属性的修改不会影响锁的情况\u003C/li\u003E\n\u003C/ul\u003E","736023":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo\"\u003E\u003C/a\u003E1. 示例demo\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epackage com.bjsxt.height.fxz;\n\n\nimport java.text.SimpleDateFormat;\nimport java.util.Date;\nimport java.util.concurrent.*;\n\n/**\n * \u0026lt;p\u0026gt;\n * 类描述 :\n * \u0026lt;/p\u0026gt;\n *\n * @author 伊凡\n * @version 0.1\n * @since 2018/9/7\n */\npublic class SelfThreadPoolTest {\n\n    private static final SimpleDateFormat format = new SimpleDateFormat(\"yyyy-MM-dd HH:mm:ss\");\n\n    /**\n     * 测试线程类\n     */\n    static class TempTask implements Runnable {\n\n        private int taskId;\n\n        public TempTask(int taskId) {\n            this.taskId = taskId;\n        }\n\n        @Override\n        public void run() {\n            System.out.println(format.format(new Date()) + \" 线程：\" + taskId + \"开始执行了\");\n            try {\n                Thread.sleep(1000);\n            } catch (InterruptedException e) {\n                e.printStackTrace();\n            }\n        }\n    }\n\n    /**\n     * 在使用有界队列时，若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，\n     * 若大于corePoolSize，则会将任务加入队列，\n     * 若队列已满，则在总线程数不大于maximumPoolSize的前提下，创建新的线程，\n     * 若线程数大于maximumPoolSize，则执行拒绝策略。或其他自定义方式。\n     */\n    public static void testArrayBlockQueueThreadPool() {\n        ExecutorService executorService = new ThreadPoolExecutor(\n                1, 2,\n                60, TimeUnit.SECONDS,\n                new ArrayBlockingQueue\u0026lt;Runnable\u0026gt;(3),\n//                new LinkedBlockingDeque\u0026lt;\u0026gt;(),\n                new RejectedExecutionHandler() {\n                    @Override\n                    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {\n                        TempTask tempTask = (TempTask) r;\n                        System.out.println(\"线程\" + tempTask.taskId + \" 被拒绝了\");\n                    }\n                });\n\n\n        for (int i = 0; i \u0026lt; 6; i++) {\n            executorService.execute(new TempTask(i));\n        }\n\n        executorService.shutdown();\n    }\n\n    public static void main(String[] args) {\n        testArrayBlockQueueThreadPool();\n    }\n\n\n}\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-使用有界队列\" class=\"anchor\" href=\"#2-%E4%BD%BF%E7%94%A8%E6%9C%89%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E2. 使用有界队列\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/151219_381ea909_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在使用有界队列时，若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，\u003C/li\u003E\n\u003Cli\u003E若大于corePoolSize，则会将任务加入队列，\u003C/li\u003E\n\u003Cli\u003E若队列已满，则在总线程数不大于maximumPoolSize的前提下，创建新的线程，\u003C/li\u003E\n\u003Cli\u003E若线程数大于maximumPoolSize，则执行拒绝策略。或其他自定义方式。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-使用无界队列\" class=\"anchor\" href=\"#3-%E4%BD%BF%E7%94%A8%E6%97%A0%E7%95%8C%E9%98%9F%E5%88%97\"\u003E\u003C/a\u003E3. 使用无界队列\u003C/h3\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/0907/151251_726c0312_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E在使用有界队列时，若有新的任务需要执行，如果线程池实际线程数小于corePoolSize，则优先创建线程，\u003C/li\u003E\n\u003Cli\u003E若大于corePoolSize，则会将任务加入队列，\u003C/li\u003E\n\u003Cli\u003E无界队列会快速增长，直到耗尽系统内存\u003C/li\u003E\n\u003C/ul\u003E","987028":"\u003Ch3\u003E\n\u003Ca id=\"1-参考链接\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5\"\u003E\u003C/a\u003E1. 参考链接\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://blog.csdn.net/test1280/article/details/70859797\"\u003ELinux：Subversion客户端安装及配置\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"http://subversion.apache.org/packages.html\"\u003ESVN 官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-yum-方式安装\" class=\"anchor\" href=\"#2-yum-%E6%96%B9%E5%BC%8F%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. yum 方式安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E安装命令\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install subversion\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/103525_2b8f31cc_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/103618_15248ec3_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\n\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1109/103912_51cc5e7f_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E查看安装路径\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost tar]# which svn\n/usr/bin/svn\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-安装服务端\" class=\"anchor\" href=\"#3-%E5%AE%89%E8%A3%85%E6%9C%8D%E5%8A%A1%E7%AB%AF\"\u003E\u003C/a\u003E3. 安装服务端\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install mod_dav_svn\n\u003C/code\u003E\u003C/pre\u003E","1018780":"\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003E序号\u003C/th\u003E\n\u003Cth\u003E命令\u003C/th\u003E\n\u003Cth\u003E描述\u003C/th\u003E\n\u003Cth\u003E示例\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1\u003C/td\u003E\n\u003Ctd\u003Edel key\u003C/td\u003E\n\u003Ctd\u003E该命令用于在 key 存在时删除 key。\u003C/td\u003E\n\u003Ctd\u003Edel w3ckey\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2\u003C/td\u003E\n\u003Ctd\u003Edump key\u003C/td\u003E\n\u003Ctd\u003E序列化给定 key ，并返回被序列化的值。\u003C/td\u003E\n\u003Ctd\u003EDUMP greeting\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E3\u003C/td\u003E\n\u003Ctd\u003Eexists key\u003C/td\u003E\n\u003Ctd\u003E检查给定 key 是否存在。\u003C/td\u003E\n\u003Ctd\u003Eexists key\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E4\u003C/td\u003E\n\u003Ctd\u003Eexpire key seconds\u003C/td\u003E\n\u003Ctd\u003E为给定 key 设置过期时间，以秒计。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E5\u003C/td\u003E\n\u003Ctd\u003Eexpireat key timestamp\u003C/td\u003E\n\u003Ctd\u003E为 key 设置过期时间。接受的时间参数是 UNIX 时间戳(unix timestamp)\u003C/td\u003E\n\u003Ctd\u003EEXPIREAT runoobkey 1293840000\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E6\u003C/td\u003E\n\u003Ctd\u003Epexpire key milliseconds\u003C/td\u003E\n\u003Ctd\u003E设置 key 的过期时间以毫秒计。\u003C/td\u003E\n\u003Ctd\u003EPEXPIRE mykey 1500\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E7\u003C/td\u003E\n\u003Ctd\u003Epexpireat key milliseconds-timestamp\u003C/td\u003E\n\u003Ctd\u003E设置 key 过期时间的时间戳(unix timestamp) 以毫秒计\u003C/td\u003E\n\u003Ctd\u003EPEXPIREAT runoobkey 1555555555005\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E8\u003C/td\u003E\n\u003Ctd\u003Ekeys pattern\u003C/td\u003E\n\u003Ctd\u003E查找所有符合给定模式( pattern)的 key 。\u003C/td\u003E\n\u003Ctd\u003EKEYS runoob*\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E9\u003C/td\u003E\n\u003Ctd\u003Emove key db\u003C/td\u003E\n\u003Ctd\u003E将当前数据库的 key 移动到给定的数据库 db 当中。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E10\u003C/td\u003E\n\u003Ctd\u003Epersist key\u003C/td\u003E\n\u003Ctd\u003E移除 key 的过期时间，key 将持久保持。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E11\u003C/td\u003E\n\u003Ctd\u003Epttl key\u003C/td\u003E\n\u003Ctd\u003E以毫秒为单位返回 key 的剩余的过期时间。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E12\u003C/td\u003E\n\u003Ctd\u003Ettl key\u003C/td\u003E\n\u003Ctd\u003E以秒为单位，返回给定 key 的剩余生存时间(ttl, time to live)。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E13\u003C/td\u003E\n\u003Ctd\u003Erandomkey\u003C/td\u003E\n\u003Ctd\u003E从当前数据库中随机返回一个 key 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E14\u003C/td\u003E\n\u003Ctd\u003Erename key newkey\u003C/td\u003E\n\u003Ctd\u003E修改 key 的名称\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E15\u003C/td\u003E\n\u003Ctd\u003Erenamenx key newkey\u003C/td\u003E\n\u003Ctd\u003E仅当 newkey 不存在时，将 key 改名为 newkey 。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E16\u003C/td\u003E\n\u003Ctd\u003Etype key\u003C/td\u003E\n\u003Ctd\u003E返回 key 所储存的值的类型。\u003C/td\u003E\n\u003Ctd\u003E\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E","680440":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo-常量锁死锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo-%E5%B8%B8%E9%87%8F%E9%94%81%E6%AD%BB%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo 常量锁（死锁）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class StringLock {\n\n\tpublic void method() {\n\t\t//new String(\"字符串常量\")\n\t\tsynchronized (\"字符串常量\") {\n\t\t\ttry {\n\t\t\t\twhile(true){\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"开始\");\n\t\t\t\t\tThread.sleep(1000);\t\t\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \"结束\");\n\t\t\t\t}\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal StringLock stringLock = new StringLock();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tstringLock.method();\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\tstringLock.method();\n\t\t\t}\n\t\t},\"t2\");\n\t\t\n\t\tt1.start();\n\t\tt2.start();\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例说明\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8B%E8%AF%B4%E6%98%8E\"\u003E\u003C/a\u003E2. 示例说明\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用常量锁，常量永远只是一个对象，当第一个线程获取锁后，如果不释放，其它线程永远获取不到锁\u003C/li\u003E\n\u003Cli\u003E可以使用new String(\"字符串常量\") 代替\u003C/li\u003E\n\u003C/ul\u003E","736129":"\u003Ch3\u003E\n\u003Ca id=\"1-jdk内置了四种拒绝策略\" class=\"anchor\" href=\"#1-jdk%E5%86%85%E7%BD%AE%E4%BA%86%E5%9B%9B%E7%A7%8D%E6%8B%92%E7%BB%9D%E7%AD%96%E7%95%A5\"\u003E\u003C/a\u003E1. JDK内置了四种拒绝策略：\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003EAbortPolicy策略\n该策略直接抛出异常，阻止系统工作\u003C/li\u003E\n\u003Cli\u003ECallerRunsPolicy策略\n只要线程池未关闭，该策略直接在调用者线程中运行当前被丢弃的任务。显然这样不会真的丢弃任务，但是，调用者线程性能可能急剧下降。\u003C/li\u003E\n\u003Cli\u003EDiscardOledestPolicy策略\n丢弃最老的一个请求任务，也就是丢弃一个即将被执行的任务，并尝试再次提交当前任务。\u003C/li\u003E\n\u003Cli\u003EDiscardPolicy策略\n默默的丢弃无法处理的任务，不予任何处理。\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-实现rejectedexecutiohandler接口自定义拒绝策略\" class=\"anchor\" href=\"#2-%E5%AE%9E%E7%8E%B0rejectedexecutiohandler%E6%8E%A5%E5%8F%A3%E8%87%AA%E5%AE%9A%E4%B9%89%E6%8B%92%E7%BB%9D%E7%AD%96%E7%95%A5\"\u003E\u003C/a\u003E2. 实现RejectedExecutioHandler接口，自定义拒绝策略\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic interfaceRejectedExecutionHandler{\n    void rejectedExecution(Runnable r,ThreadPoolExecutor executor);\n}\n\u003C/code\u003E\u003C/pre\u003E","987029":"\u003Ch4\u003E\n\u003Ca id=\"1-下载frp\" class=\"anchor\" href=\"#1-%E4%B8%8B%E8%BD%BDfrp\"\u003E\u003C/a\u003E1. 下载frp\u003C/h4\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/fatedier/frp/blob/master/README_zh.md\"\u003Egit 地址\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/fatedier/frp/releases\"\u003E安装包下载\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E1.1 解压tar\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf frp_0.17.0_linux_amd64.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1.2 配置frps服务端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[common]\nbind_port = 7000\nvhost_http_port = 9080\nvhost_https_port = 443\n\n\ndashboard_port = 7500\n# dashboard 用户名密码，默认都为 admin\ndashboard_user = admin\ndashboard_pwd = admin\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1.3 配置frpc客户端\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[common]\nserver_addr = 39.106.64.79\nserver_port = 7000\n\n[web]\ntype = http\nlocal_port = 8080\ncustom_domains = xcx.xlauch.com\n\n[web01]\ntype = https\nlocal_port = 443\ncustom_domains = xcx.xlauch.com\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E1.4 命令\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 启动服务端\nsetsid ./frps -c frps.ini \n\n# 启动客户端\nsetsid ./frpc -c frpc.ini \n\u003C/code\u003E\u003C/pre\u003E","684166":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo死锁\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E6%AD%BB%E9%94%81\"\u003E\u003C/a\u003E1. 示例demo（死锁）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class DeadLock implements Runnable{\n\n\tprivate String tag;\n\tprivate static Object lock1 = new Object();\n\tprivate static Object lock2 = new Object();\n\t\n\tpublic void setTag(String tag){\n\t\tthis.tag = tag;\n\t}\n\t\n\t@Override\n\tpublic void run() {\n\t\tif(tag.equals(\"a\")){\n\t\t\tsynchronized (lock1) {\n\t\t\t\ttry {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock1执行\");\n\t\t\t\t\tThread.sleep(2000);\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t\tsynchronized (lock2) {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock2执行\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif(tag.equals(\"b\")){\n\t\t\tsynchronized (lock2) {\n\t\t\t\ttry {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock2执行\");\n\t\t\t\t\tThread.sleep(2000);\n\t\t\t\t} catch (InterruptedException e) {\n\t\t\t\t\te.printStackTrace();\n\t\t\t\t}\n\t\t\t\tsynchronized (lock1) {\n\t\t\t\t\tSystem.out.println(\"当前线程 : \"  + Thread.currentThread().getName() + \" 进入lock1执行\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tDeadLock d1 = new DeadLock();\n\t\td1.setTag(\"a\");\n\t\tDeadLock d2 = new DeadLock();\n\t\td2.setTag(\"b\");\n\t\t \n\t\tThread t1 = new Thread(d1, \"t1\");\n\t\tThread t2 = new Thread(d2, \"t2\");\n\t\t \n\t\tt1.start();\n\t\ttry {\n\t\t\tThread.sleep(500);\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t\tt2.start();\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Et1在执行过程中，请求获取t2锁，t2在执行过程中，又请求t1锁，从而导致死锁\u003C/li\u003E\n\u003Cli\u003E死锁问题，在设计程序时就应该避免双方相互持有对方的锁的情况\u003C/li\u003E\n\u003C/ul\u003E","987030":"\u003Ch3\u003E\n\u003Ca id=\"1-源码安装\" class=\"anchor\" href=\"#1-%E6%BA%90%E7%A0%81%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E1. 源码安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(1) 安装nginx所需环境：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install gcc\nyum install pcre-devel\nyum install zlib zlib-devel\nyum install openssl openssl-devel\n或者一键安装：yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(2) 下载nginx压缩包：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Ca href=\"http://nginx.org/en/download.html\"\u003Enginx下载地址\u003C/a\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewget http://nginx.org/download/nginx-1.10.2.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(3) 解压缩：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Etar -zxvf nginx-1.10.2.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(4) 编译、安装\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd nginx-1.10.2\n./configure\nmake\nmake install\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(5) 查找nginx安装目录：\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewhereis nginx\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(6) 启动Nginx\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd /usr/local/nginx/\ncd sbin\n./nginx\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E(7) 打开浏览器，输入ip地址，看到welcome to nginx！即安装成功\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cimg src=\"https://static.oschina.net/uploads/img/201805/05104005_ylWF.png\" alt=\"输入图片说明\" title=\"在这里输入图片标题\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-yum-安装\" class=\"anchor\" href=\"#2-yum-%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. yum 安装\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum install nginx\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E命令\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E#启动\nservice nginx start\n\n#停止\nservice nginx stop\n\n#重启\nservice nginx restart\n\n#另一方式重启\ncd /usr/local/nginx/sbin\n./nginx -s reload\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ecd /etc/nginx/conf.d\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置tomcat映射\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim tomcat.conf\n\nserver {\n        listen 80;\n        server_name www.xlauch.com;\n        keepalive_timeout 70;\n        proxy_set_header \"Host\" $host:8080;\n        location / {\n                proxy_pass_header Server;\n                proxy_redirect http://$host:8080 http://$host;\n                proxy_pass http://127.0.0.1:8080;\n                proxy_buffer_size 64k;\n                proxy_buffers   32 32k;\n                proxy_busy_buffers_size 128k;\n        }\n        access_log off;\n        log_not_found off;\n}\n\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E配置frp映射\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim frp.conf\n\nserver {\n        listen 80;\n        server_name *.frp.xlauch.com fxz.xlauch.com xcx.xlauch.com hxy.xlauch.com;\n        keepalive_timeout 70;\n        proxy_set_header \"Host\" $host:9080;\n        location / {\n                proxy_pass_header Server;\n                proxy_redirect http://$host:9080 http://$host;\n                proxy_pass http://127.0.0.1:9080;\n                proxy_buffer_size 64k;\n                proxy_buffers   32 32k;\n                proxy_busy_buffers_size 128k;\n        }\n        access_log off;\n        log_not_found off;\n}\n\u003C/code\u003E\u003C/pre\u003E","684588":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo锁的粒度\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo%E9%94%81%E7%9A%84%E7%B2%92%E5%BA%A6\"\u003E\u003C/a\u003E1. 示例demo（锁的粒度）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class Optimize {\n\n\tpublic void doLongTimeTask(){\n\t\ttry {\n\t\t\t\n\t\t\tSystem.out.println(\"当前线程开始：\" + Thread.currentThread().getName() + \n\t\t\t\t\t\", 正在执行一个较长时间的业务操作，其内容不需要同步\");\n\t\t\tThread.sleep(2000);\n\t\t\t\n\t\t\tsynchronized(this){\n\t\t\t\tSystem.out.println(\"当前线程：\" + Thread.currentThread().getName() + \n\t\t\t\t\t\", 执行同步代码块，对其同步变量进行操作\");\n\t\t\t\tThread.sleep(1000);\n\t\t\t}\n\t\t\tSystem.out.println(\"当前线程结束：\" + Thread.currentThread().getName() +\n\t\t\t\t\t\", 执行完毕\");\n\t\t\t\n\t\t} catch (InterruptedException e) {\n\t\t\te.printStackTrace();\n\t\t}\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\tfinal Optimize otz = new Optimize();\n\t\tThread t1 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\totz.doLongTimeTask();\n\t\t\t}\n\t\t},\"t1\");\n\t\tThread t2 = new Thread(new Runnable() {\n\t\t\t@Override\n\t\t\tpublic void run() {\n\t\t\t\totz.doLongTimeTask();\n\t\t\t}\n\t\t},\"t2\");\n\t\tt1.start();\n\t\tt2.start();\n\t\t\n\t}\n\t\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E使用synchronized代码块减小锁的粒度，提高性能\u003C/li\u003E\n\u003C/ul\u003E","988485":"\u003Ch3\u003E\n\u003Ca id=\"1-参考资料\" class=\"anchor\" href=\"#1-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E1. 参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://www.cnblogs.com/zuidongfeng/p/8032505.html\"\u003ECentos7下安装Redis\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Ca href=\"https://redis.io/download\"\u003ERedis 官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-编译安装\" class=\"anchor\" href=\"#2-%E7%BC%96%E8%AF%91%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E2. 编译安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E下载源码包\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Ewget http://download.redis.io/releases/redis-4.0.11.tar.gz\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压安装\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# yum安装gcc依赖 （如果已经有就跳过此步骤）\n[fxz@localhost redis-4.0.11]$ yum install gcc　　\n\n# 解压\n[fxz@localhost redis-4.0.11]$ tar -zxvf redis-4.0.11.tar.gz \n\n# 编译\n[fxz@localhost redis-4.0.11]$ make MALLOC=libc\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/161439_494a2279_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 必须用root安装\n[root@localhost redis-4.0.11]# cd src \u0026amp;\u0026amp; make install\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/161616_487299ce_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-修改配置\" class=\"anchor\" href=\"#3-%E4%BF%AE%E6%94%B9%E9%85%8D%E7%BD%AE\"\u003E\u003C/a\u003E3. 修改配置\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-4.0.11]# cp redis.conf redis.conf.bak\n[root@localhost redis-4.0.11]# mkdir logs\n[root@localhost redis-4.0.11]# vim redis.conf\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Eredis.conf\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 设置从后台启动\ndaemonize yes\n\n# 设置日志存放目录\nlogfile \"/usr/local/deve/soft/redis-4.0.11/logs/redis.log\"\n\n# 绑定主机IP\nbind 主机IP\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4-启动关闭\" class=\"anchor\" href=\"#4-%E5%90%AF%E5%8A%A8%E5%85%B3%E9%97%AD\"\u003E\u003C/a\u003E4. 启动、关闭\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E启动\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 指定配置文件启动\n[root@localhost src]# ./redis-server ../redis.conf\n\n[root@localhost src]# ps -ef | grep redis\nroot      10562      1  0 16:27 ?        00:00:00 ./redis-server 127.0.0.1:6379\nroot      10575  10280  0 16:27 pts/0    00:00:00 grep --color=auto redis\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E连接\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 进入客户端\n[root@localhost src]# ./redis-cli \n\n# 查看所有键\n127.0.0.1:6379\u0026gt; key *\n(error) ERR unknown command `key`, with args beginning with: `*`, \n\n# 设值\n127.0.0.1:6379\u0026gt; set name fxz\nOK\n\n# 取值\n127.0.0.1:6379\u0026gt; get name\n\"fxz\"\n127.0.0.1:6379\u0026gt; \n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E关闭\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 退出客户端\n127.0.0.1:6379\u0026gt; quit\n\n# 退出服务端方式一\n[root@localhost src]# ./redis-cli shutdown\n\n# 退出服务端方式二\n[root@localhost src]# ./redis-server ../redis.conf\n[root@localhost src]# ps -ef | grep redis\nroot      10691      1  0 16:32 ?        00:00:00 ./redis-server 127.0.0.1:6379\nroot      10696  10280  0 16:32 pts/0    00:00:00 grep --color=auto redis\n[root@localhost src]# kill -9 10691\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5-数据保存\" class=\"anchor\" href=\"#5-%E6%95%B0%E6%8D%AE%E4%BF%9D%E5%AD%98\"\u003E\u003C/a\u003E5. 数据保存\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost redis-4.0.11]# vim redis.conf\n\n\n# 默认文件名\ndbfilename dump.rdb\n\n# The working directory.\n#\n# The DB will be written inside this directory, with the filename specified\n# above using the 'dbfilename' configuration directive.\n#\n# The Append Only File will also be created inside this directory.\n#\n# 数据存放路径\ndir ./\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1113/163721_7f3d9314_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"常见问题\" class=\"anchor\" href=\"#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E常见问题\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E/bin/sh: cc: command not found\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esudo yum -y install gcc gcc-c++ libstdc++-devel \nmake MALLOC=libc\n\u003C/code\u003E\u003C/pre\u003E","684683":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo1\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo1\"\u003E\u003C/a\u003E1. 示例demo1\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class RunThread extends Thread{\n\n\tprivate volatile boolean isRunning = true;\n\tprivate void setRunning(boolean isRunning){\n\t\tthis.isRunning = isRunning;\n\t}\n\t\n\tpublic void run(){\n\t\tSystem.out.println(\"进入run方法..\");\n\t\tint i = 0;\n\t\twhile(isRunning == true){\n\t\t\t//..\n\t\t}\n\t\tSystem.out.println(\"线程停止\");\n\t}\n\t\n\tpublic static void main(String[] args) throws InterruptedException {\n\t\tRunThread rt = new RunThread();\n\t\trt.start();\n\t\tThread.sleep(1000);\n\t\trt.setRunning(false);\n\t\tSystem.out.println(\"isRunning的值已经被设置了false\");\n\t}\n\t\n\t\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E如果变量\"isRunning\"没有volatile 进行修饰，那么进程就无法停止，因为main线程与rt线程中isRunning无法共用\u003C/li\u003E\n\u003Cli\u003E使用\"volatile\"关键字对变量进行修饰后，可以让\"isRunning\"可以在多个线程中相互可见\u003C/li\u003E\n\u003C/ul\u003E","1031999":"\u003Ch3\u003E\n\u003Ca id=\"一在线下载docker\" class=\"anchor\" href=\"#%E4%B8%80%E5%9C%A8%E7%BA%BF%E4%B8%8B%E8%BD%BDdocker\"\u003E\u003C/a\u003E一、在线下载docker\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.cnblogs.com/qingyunzong/p/9011006.html\"\u003ECentOS7 安装Docker\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum update\n\nyum install -y epel-release\n\nyum install docker-io       # 安装docker\n\nchkconfig docker on         # 加入开机启动\n\nsystemctl start docker      # 启动docker服务\n\nsystemctl restart docker      # 重启docker服务\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"二测试验证\" class=\"anchor\" href=\"#%E4%BA%8C%E6%B5%8B%E8%AF%95%E9%AA%8C%E8%AF%81\"\u003E\u003C/a\u003E二、测试验证\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 查看版本\ndocker -v\n\n#运行容器\ndocker run hello-world\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"三设置镜像\" class=\"anchor\" href=\"#%E4%B8%89%E8%AE%BE%E7%BD%AE%E9%95%9C%E5%83%8F\"\u003E\u003C/a\u003E三、设置镜像\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E参考 \u003Ca href=\"https://cr.console.aliyun.com/cn-shenzhen/mirrors\"\u003Ehttps://cr.console.aliyun.com/cn-shenzhen/mirrors\u003C/a\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evi /etc/docker/daemon.json\n\n{\n  \"registry-mirrors\": [\"https://aj2rgad5.mirror.aliyuncs.com\"]\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E立即生效\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E#使生效\nsudo systemctl daemon-reload\n\n#重启docker服务\nsudo systemctl restart docker\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"常见问题\" class=\"anchor\" href=\"#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E常见问题\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"1-error-starting-daemon-selinux-is-not-supported-with-the-overlay2-graph-driver-on-this-kernel-eithe\" class=\"anchor\" href=\"#1-error-starting-daemon-selinux-is-not-supported-with-the-overlay2-graph-driver-on-this-kernel-eithe\"\u003E\u003C/a\u003E1. Error starting daemon: SELinux is not supported with the overlay2 graph driver on this kernel. Eithe\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Evi /etc/sysconfig/docker\n \n\nOPTIONS='--selinux-enabled=false  --log-driver=journald --signature-verification=false'\nif [ -z \"${DOCKER_CERT_PATH}\" ]; then\n    DOCKER_CERT_PATH=/etc/docker\nfi\n\n:wq \n\u003C/code\u003E\u003C/pre\u003E","684860":"\u003Ch3\u003E\n\u003Ca id=\"1-示例demo1\" class=\"anchor\" href=\"#1-%E7%A4%BA%E4%BE%8Bdemo1\"\u003E\u003C/a\u003E1. 示例demo1\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class VolatileNoAtomic extends Thread{\n\t//private static volatile int count;\n\tprivate static AtomicInteger count = new AtomicInteger(0);\n\tprivate static void addCount(){\n\t\tfor (int i = 0; i \u0026lt; 1000; i++) {\n\t\t\t//count++ ;\n\t\t\tcount.incrementAndGet();\n\t\t}\n\t\tSystem.out.println(count);\n\t}\n\t\n\tpublic void run(){\n\t\taddCount();\n\t}\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tVolatileNoAtomic[] arr = new VolatileNoAtomic[100];\n\t\tfor (int i = 0; i \u0026lt; 10; i++) {\n\t\t\tarr[i] = new VolatileNoAtomic();\n\t\t}\n\t\t\n\t\tfor (int i = 0; i \u0026lt; 10; i++) {\n\t\t\tarr[i].start();\n\t\t}\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003Evolatile关键字不具备synchronized关键字的原子性（同步），每次结果都不一样\u003C/li\u003E\n\u003Cli\u003E使用AtomicInteger 可以保证原子性，最终结果都为1000*10\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-示例demo2\" class=\"anchor\" href=\"#2-%E7%A4%BA%E4%BE%8Bdemo2\"\u003E\u003C/a\u003E2. 示例demo2\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Epublic class AtomicUse {\n\n\tprivate static AtomicInteger count = new AtomicInteger(0);\n\t\n\t//多个addAndGet在一个方法内是非原子性的，需要加synchronized进行修饰，保证4个addAndGet整体原子性\n\t/**synchronized*/\n\tpublic synchronized int multiAdd(){\n\t\t\ttry {\n\t\t\t\tThread.sleep(100);\n\t\t\t} catch (InterruptedException e) {\n\t\t\t\te.printStackTrace();\n\t\t\t}\n\t\t\tcount.addAndGet(1);\n\t\t\tcount.addAndGet(2);\n\t\t\tcount.addAndGet(3);\n\t\t\tcount.addAndGet(4); //+10\n\t\t\treturn count.get();\n\t}\n\t\n\t\n\tpublic static void main(String[] args) {\n\t\t\n\t\tfinal AtomicUse au = new AtomicUse();\n\n\t\tList\u0026lt;Thread\u0026gt; ts = new ArrayList\u0026lt;Thread\u0026gt;();\n\t\tfor (int i = 0; i \u0026lt; 100; i++) {\n\t\t\tts.add(new Thread(new Runnable() {\n\t\t\t\t@Override\n\t\t\t\tpublic void run() {\n\t\t\t\t\tSystem.out.println(au.multiAdd());\n\t\t\t\t}\n\t\t\t}));\n\t\t}\n\n\t\tfor(Thread t : ts){\n\t\t\tt.start();\n\t\t}\n\t}\n}\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E多个addAndGet在一个方法内是非原子性的，需要加synchronized进行修饰，保证4个addAndGet整体原子性\u003C/li\u003E\n\u003C/ul\u003E","1032058":"\u003Ch3\u003E\n\u003Ca id=\"一参考资料\" class=\"anchor\" href=\"#%E4%B8%80%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E一、参考资料\u003C/h3\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/jimmy201602/webterminal\"\u003Ewebterminal git官网\u003C/a\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"二安装\" class=\"anchor\" href=\"#%E4%BA%8C%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E二、安装\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 国内请使用阿里云镜像\ndocker pull registry.cn-hangzhou.aliyuncs.com/webterminal/webterminal \ndocker run -itd -p 80:80 registry.cn-hangzhou.aliyuncs.com/webterminal/webterminal \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"三登录\" class=\"anchor\" href=\"#%E4%B8%89%E7%99%BB%E5%BD%95\"\u003E\u003C/a\u003E三、登录\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eusername: admin\npassword: password!23456\n\u003C/code\u003E\u003C/pre\u003E","1035589":"\u003Ch3\u003E\n\u003Ca id=\"0参考资料\" class=\"anchor\" href=\"#0%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E0、参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://www.linuxidc.com/Linux/2017-05/143346.htm\"\u003ECentOS7.1安装VNC，让Win7远程桌面Linux\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"https://jingyan.baidu.com/article/86f4a73e9c937537d652691e.html\"\u003ECentOS 7.2 安装配置VNC\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1安装x-window\" class=\"anchor\" href=\"#1%E5%AE%89%E8%A3%85x-window\"\u003E\u003C/a\u003E1、安装X-Window\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Eyum check-update\nyum groupinstall \"X Window System\"\nyum install gnome-classic-session gnome-terminal nautilus-open-terminal control-center liberation-mono-fonts\nunlink /etc/systemd/system/default.target\nln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target\nreboot #重启机器\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2安装vncserver\" class=\"anchor\" href=\"#2%E5%AE%89%E8%A3%85vncserver\"\u003E\u003C/a\u003E2、安装VNCServer\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E#检查是否安装VNC \nrpm -q tigervnc tigervnc-server\n\nyum install tigervnc tigervnc-server\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3配置nvc\" class=\"anchor\" href=\"#3%E9%85%8D%E7%BD%AEnvc\"\u003E\u003C/a\u003E3、配置NVC\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E# 将/lib/systemd/system/vncserver@.service文件复制一份\n\ncp /lib/systemd/system/vncserver@.service /etc/systemd/system/vncserver@:1.service\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"4编辑刚刚我们复制得新文件\" class=\"anchor\" href=\"#4%E7%BC%96%E8%BE%91%E5%88%9A%E5%88%9A%E6%88%91%E4%BB%AC%E5%A4%8D%E5%88%B6%E5%BE%97%E6%96%B0%E6%96%87%E4%BB%B6\"\u003E\u003C/a\u003E4、编辑刚刚我们复制得新文件\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E设置root用户\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Evim /etc/systemd/system/vncserver@:1.service\n\n\n# 把\u0026lt;USER\u0026gt; 替换成root\n# Clean any existing files in /tmp/.X11-unix environment\nExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n#ExecStart=/usr/sbin/runuser -l root -c \"/usr/bin/vncserver %i\"\n#PIDFile=/root/.vnc/%H%i.pid\n\nExecStart=/sbin/runuser -l root -c \"/usr/bin/vncserver %i\" \nPIDFile=/root/.vnc/%H%i.pid\n\nExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E设置非root用户\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E# Clean any existing files in /tmp/.X11-unix environment\nExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n#ExecStart=/usr/sbin/runuser -l root -c \"/usr/bin/vncserver %i\"\n#PIDFile=/root/.vnc/%H%i.pid\n\nExecStart=/sbin/runuser -l fxz -c \"/usr/bin/vncserver %i\"\nPIDFile=/home/fxz/.vnc/%H%i.pid\n\nExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i \u0026gt; /dev/null 2\u0026gt;\u0026amp;1 || :'\n\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E设置非root用户密码\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003Esu fxz\nvncpasswd\n\u003C/code\u003E\u003C/pre\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E修改VNC 分辨率\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cpre\u003E\u003Ccode\u003E[root@localhost ~]# vi /usr/bin/vncserver \n\n$geometry = “1280×1024″;  \n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"5重新加载-systemd\" class=\"anchor\" href=\"#5%E9%87%8D%E6%96%B0%E5%8A%A0%E8%BD%BD-systemd\"\u003E\u003C/a\u003E5、重新加载 systemd\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E#由于在systemd中添加了东东,得让系统重新加载\nsystemctl daemon-reload\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"6设置vncserver开机自启动\" class=\"anchor\" href=\"#6%E8%AE%BE%E7%BD%AEvncserver%E5%BC%80%E6%9C%BA%E8%87%AA%E5%90%AF%E5%8A%A8\"\u003E\u003C/a\u003E6、设置VNCServer开机自启动\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\n# VNCServer开机自启动\nsystemctl enable vncserver@:1.service\n\n# 启动\nsystemctl start vncserver@:1.service\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"7设置密码8898081\" class=\"anchor\" href=\"#7%E8%AE%BE%E7%BD%AE%E5%AF%86%E7%A0%818898081\"\u003E\u003C/a\u003E7、设置密码（8898081）\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003Evncpasswd\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"8客户端连接\" class=\"anchor\" href=\"#8%E5%AE%A2%E6%88%B7%E7%AB%AF%E8%BF%9E%E6%8E%A5\"\u003E\u003C/a\u003E8、客户端连接\u003C/h3\u003E\n\u003Cp\u003E下载VNC Viewer ：\u003Ca href=\"http://www.realvnc.com/download/viewer/\"\u003Ehttp://www.realvnc.com/download/viewer/\u003C/a\u003E\u003C/p\u003E\n\u003Cp\u003E\u003Cimg src=\"https://images.gitee.com/uploads/images/2018/1123/144939_f95433b5_907621.png\" alt=\"输入图片说明\" title=\"屏幕截图.png\"\u003E\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"9常见错误\" class=\"anchor\" href=\"#9%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF\"\u003E\u003C/a\u003E9、常见错误\u003C/h3\u003E\n\u003Ch4\u003E\n\u003Ca id=\"job-for-vncserver1service-failed-because-the-control-process-exited-with-error-code-see-systemctl-status-vncserver1service-and-journalctl--xe-for-details\" class=\"anchor\" href=\"#job-for-vncserver1service-failed-because-the-control-process-exited-with-error-code-see-systemctl-status-vncserver1service-and-journalctl--xe-for-details\"\u003E\u003C/a\u003EJob for vncserver@:1.service failed because the control process exited with error code. See \"systemctl status vncserver@:1.service\" and \"journalctl -xe\" for details.\u003C/h4\u003E\n\u003Cpre\u003E\u003Ccode\u003Erm -f -R /tmp/.X11-unix/\n\nsystemctl enable vncserver@:1.service\n\u003C/code\u003E\u003C/pre\u003E","1096535":"\u003Ch3\u003E\n\u003Ca id=\"参考资料\" class=\"anchor\" href=\"#%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Ca href=\"https://gogs.io/docs/installation/configuration_and_run\"\u003Egogs 说明文档\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"1-环境要求\" class=\"anchor\" href=\"#1-%E7%8E%AF%E5%A2%83%E8%A6%81%E6%B1%82\"\u003E\u003C/a\u003E1. 环境要求\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E数据库（选择以下一项）：\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Ca href=\"http://dev.mysql.com\"\u003EMySQL\u003C/a\u003E：版本 \u0026gt;= 5.7\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"http://www.postgresql.org/\"\u003EPostgreSQL\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"https://en.wikipedia.org/wiki/Microsoft_SQL_Server\"\u003EMSSQL\u003C/a\u003E\u003C/li\u003E\n\u003Cli\u003E\n\u003Ca href=\"https://github.com/pingcap/tidb\"\u003ETiDB\u003C/a\u003E（实验性支持，使用 MySQL 协议连接）\u003C/li\u003E\n\u003Cli\u003E或者 \u003Cstrong\u003E什么都不安装\u003C/strong\u003E 直接使用 SQLite3\u003C/li\u003E\n\u003C/ul\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Ca href=\"http://git-scm.com/\"\u003Egit\u003C/a\u003E（bash）：\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E服务端和客户端均需版本 \u0026gt;= 1.7.1\u003C/li\u003E\n\u003Cli\u003EWindows 系统建议使用最新版\u003C/li\u003E\n\u003C/ul\u003E\n\u003C/li\u003E\n\u003Cli\u003ESSH 服务器：\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\u003Cstrong\u003E如果您只使用 HTTP/HTTPS 的话请忽略此项\u003C/strong\u003E\u003C/li\u003E\n\u003Cli\u003E如果您选择在 Windows 系统使用内置 SSH 服务器，请确保添加 \u003Ccode\u003Essh-keygen\u003C/code\u003E 到您的 \u003Ccode\u003E%PATH%\u003C/code\u003E 环境变量中\u003C/li\u003E\n\u003Cli\u003E推荐 Windows 系统使用 \u003Ca href=\"http://docs.oracle.com/cd/E24628_01/install.121/e22624/preinstall_req_cygwin_ssh.htm\"\u003ECygwin OpenSSH\u003C/a\u003E 或 \u003Ca href=\"https://www.itefix.net/copssh\"\u003ECopssh\u003C/a\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-安装数据库\" class=\"anchor\" href=\"#2-%E5%AE%89%E8%A3%85%E6%95%B0%E6%8D%AE%E5%BA%93\"\u003E\u003C/a\u003E2. 安装数据库\u003C/h3\u003E\n\u003Cp\u003E请根据您的选择进行安装：\u003C/p\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Ca href=\"http://dev.mysql.com/downloads/mysql/\"\u003EMySQL\u003C/a\u003E（引擎：INNODB）\u003C/li\u003E\n\u003Cli\u003E\u003Ca href=\"http://www.postgresql.org/download/\"\u003EPostgreSQL\u003C/a\u003E\u003C/li\u003E\n\u003C/ul\u003E\n\u003Cp\u003E\u003Cstrong\u003E注意事项\u003C/strong\u003E 您可以使用 \u003Ccode\u003Eetc/mysql.sql\u003C/code\u003E 来自动创建名为 \u003Ccode\u003Egogs\u003C/code\u003E 的数据库。如果您选择手动创建，请务必将编码设置为 \u003Ccode\u003Eutf8mb4\u003C/code\u003E。\u003C/p\u003E\n\u003Ch3\u003E\n\u003Ca id=\"3-二进制安装\" class=\"anchor\" href=\"#3-%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%AE%89%E8%A3%85\"\u003E\u003C/a\u003E3. 二进制安装\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E解压压缩包。\u003C/li\u003E\n\u003Cli\u003E使用命令 cd 进入到刚刚创建的目录。\u003C/li\u003E\n\u003Cli\u003E执行命令 nohup ./gogs web \u0026amp; ，默认端口3000\u003C/li\u003E\n\u003Cli\u003E然后访问 /install 来完成首次运行的配置工作\u003C/li\u003E\n\u003C/ul\u003E","1331224":"\u003Ch3\u003E\n\u003Ca id=\"1-打包war\" class=\"anchor\" href=\"#1-%E6%89%93%E5%8C%85war\"\u003E\u003C/a\u003E1. 打包war\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;com.google.cloud.tools\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;jib-maven-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;version\u0026gt;1.0.0\u0026lt;/version\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t\t\u0026lt;from\u0026gt;\n\t\t\t\u0026lt;!--base image--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;tomcat:8.5-jre8-alpine\u0026lt;/image\u0026gt;\n\t\t\u0026lt;/from\u0026gt;\n\t\t\u0026lt;to\u0026gt;\n\t\t\t\u0026lt;!--目标镜像registry地址，为了方便测试，你需要换成自己的地址，如果你的网络不好，可以选用国内加速器，比如阿里云的--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;registry.cn-hangzhou.aliyuncs.com/xlauch/xlauch-dubbo\u0026lt;/image\u0026gt;\n\t\t\t\u0026lt;auth\u0026gt;\n\t\t\t\t\u0026lt;username\u0026gt;hi35361525@aliyun.com\u0026lt;/username\u0026gt;\n\t\t\t\t\u0026lt;password\u0026gt;xiao8898081\u0026lt;/password\u0026gt;\n\t\t\t\u0026lt;/auth\u0026gt;\n\t\t\t\u0026lt;tags\u0026gt;\n\t\t\t\t\u0026lt;tag\u0026gt;1.0\u0026lt;/tag\u0026gt;\n\t\t\t\t\u0026lt;tag\u0026gt;latest\u0026lt;/tag\u0026gt;\n\t\t\t\u0026lt;/tags\u0026gt;\n\t\t\u0026lt;/to\u0026gt;\n\t\t\u0026lt;container\u0026gt;\n\t\t\t\u0026lt;appRoot\u0026gt;/usr/local/tomcat/webapps/ROOT\u0026lt;/appRoot\u0026gt;\n\t\t\u0026lt;/container\u0026gt;\n\n\t\u0026lt;/configuration\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t\t\u0026lt;execution\u0026gt;\n\t\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\t\u0026lt;goals\u0026gt;\n\t\t\t\t\u0026lt;goal\u0026gt;build\u0026lt;/goal\u0026gt;\n\t\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n\u0026lt;/plugin\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E\n\u003Ch3\u003E\n\u003Ca id=\"2-打包jar\" class=\"anchor\" href=\"#2-%E6%89%93%E5%8C%85jar\"\u003E\u003C/a\u003E2. 打包jar\u003C/h3\u003E\n\u003Cpre\u003E\u003Ccode\u003E\n\u0026lt;plugin\u0026gt;\n\t\u0026lt;groupId\u0026gt;com.google.cloud.tools\u0026lt;/groupId\u0026gt;\n\t\u0026lt;artifactId\u0026gt;jib-maven-plugin\u0026lt;/artifactId\u0026gt;\n\t\u0026lt;version\u0026gt;1.0.0\u0026lt;/version\u0026gt;\n\t\u0026lt;configuration\u0026gt;\n\t\t\u0026lt;from\u0026gt;\n\t\t\t\u0026lt;!--base image--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;openjdk:alpine\u0026lt;/image\u0026gt;\n\t\t\u0026lt;/from\u0026gt;\n\t\t\u0026lt;to\u0026gt;\n\t\t\t\u0026lt;!--目标镜像registry地址，为了方便测试，你需要换成自己的地址，如果你的网络不好，可以选用国内加速器，比如阿里云的--\u0026gt;\n\t\t\t\u0026lt;image\u0026gt;registry.cn-hangzhou.aliyuncs.com/xlauch/xlauch-dubbo\u0026lt;/image\u0026gt;\n                        \u0026lt;auth\u0026gt;\n                            \u0026lt;username\u0026gt;hi35361525@aliyun.com\u0026lt;/username\u0026gt;\n                            \u0026lt;password\u0026gt;xiao8898081\u0026lt;/password\u0026gt;\n                        \u0026lt;/auth\u0026gt;\n                        \u0026lt;tags\u0026gt;\n                            \u0026lt;tag\u0026gt;1.0\u0026lt;/tag\u0026gt;\n                            \u0026lt;tag\u0026gt;latest\u0026lt;/tag\u0026gt;\n                        \u0026lt;/tags\u0026gt; \n\t\t\u0026lt;/to\u0026gt;\n\t\t\u0026lt;container\u0026gt;\n\t\t\t\u0026lt;mainClass\u0026gt;com.i84.insect.svc.bootstrap.SvcStart\u0026lt;/mainClass\u0026gt;\n\t\t\u0026lt;/container\u0026gt;\n\t\u0026lt;/configuration\u0026gt;\n\t\u0026lt;executions\u0026gt;\n\t\t\u0026lt;execution\u0026gt;\n\t\t\t\u0026lt;phase\u0026gt;package\u0026lt;/phase\u0026gt;\n\t\t\t\u0026lt;goals\u0026gt;\n\t\t\t\t\u0026lt;goal\u0026gt;build\u0026lt;/goal\u0026gt;\n\t\t\t\u0026lt;/goals\u0026gt;\n\t\t\u0026lt;/execution\u0026gt;\n\t\u0026lt;/executions\u0026gt;\n\u0026lt;/plugin\u0026gt;\n\u003C/code\u003E\u003C/pre\u003E","1347359":"\u003Ch3\u003E\n\u003Ca id=\"一参考资料\" class=\"anchor\" href=\"#%E4%B8%80%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99\"\u003E\u003C/a\u003E一、参考资料\u003C/h3\u003E\n\u003Cul class=\"task-list\"\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://nacos.io/zh-cn/\"\u003Enacos官网\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://mp.weixin.qq.com/s?__biz=MzAxODcyNjEzNQ==\u0026amp;mid=2247486943\u0026amp;idx=1\u0026amp;sn=fccce227cac0843cca1f18716b0f9b46\u0026amp;chksm=9bd0a047aca72951a1a945e51cc28e0e373b75080281e7add78a964f71ec888248164e80bd40\u0026amp;scene=0\u0026amp;xtrack=1#rd\"\u003E程序猿DD\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://www.bilibili.com/video/av45084065\"\u003Epigx  spring cloud alibaba  系列教程\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003Cli\u003E\n\u003Cp\u003E\u003Ca href=\"https://github.com/spring-cloud-incubator/spring-cloud-alibaba/wiki/Nacos-discovery\"\u003E官方git教程\u003C/a\u003E\u003C/p\u003E\n\u003C/li\u003E\n\u003C/ul\u003E\n\u003Ch3\u003E\n\u003Ca id=\"二特别注意版本兼容问题\" class=\"anchor\" href=\"#%E4%BA%8C%E7%89%B9%E5%88%AB%E6%B3%A8%E6%84%8F%E7%89%88%E6%9C%AC%E5%85%BC%E5%AE%B9%E9%97%AE%E9%A2%98\"\u003E\u003C/a\u003E二、特别注意（版本兼容问题）\u003C/h3\u003E\n\u003Ctable\u003E\n\u003Cthead\u003E\n\u003Ctr\u003E\n\u003Cth\u003ESpring Boot\u003C/th\u003E\n\u003Cth\u003ESpring Cloud\u003C/th\u003E\n\u003Cth\u003ESpring Cloud Alibaba\u003C/th\u003E\n\u003C/tr\u003E\n\u003C/thead\u003E\n\u003Ctbody\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2.1.x\u003C/td\u003E\n\u003Ctd\u003EGreenwich\u003C/td\u003E\n\u003Ctd\u003E0.2.2（还未RELEASE）\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E2.0.x\u003C/td\u003E\n\u003Ctd\u003EFinchley\u003C/td\u003E\n\u003Ctd\u003E0.2.1\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1.5.x\u003C/td\u003E\n\u003Ctd\u003EEdgware\u003C/td\u003E\n\u003Ctd\u003E0.1.1\u003C/td\u003E\n\u003C/tr\u003E\n\u003Ctr\u003E\n\u003Ctd\u003E1.5.x\u003C/td\u003E\n\u003Ctd\u003EDalston\u003C/td\u003E\n\u003Ctd\u003E0.1.1\u003C/td\u003E\n\u003C/tr\u003E\n\u003C/tbody\u003E\n\u003C/table\u003E"}}</script>